: 기존 환경 내에서 반복적으로 일어나는 문제들을 어떻게 풀어나갈 것인가에 대한 일종의 솔루션
설계할 때 발생했던 문제점들을 객체 간의 상호관계 등을 이용하여 해결할 수 있도록 하나의 '규약' 형태로 만들어놓은 것
GoF의 디자인 패턴(디자인 패턴계의 교과서)에서는 객체지향적 디자인 패턴의 카테고리를 3가지로 분류
: 객체의 생성에 관련된 패턴으로, 객체의 생성절차를 추상화하는 패턴
인스턴스를 만드는 절차를 추상화하는 패턴
시스템으로부터 객체의 생성/합성 방법을 분리해내기 위함
시스템이 어떤 구체 클래스를 사용하는지, 인스턴스들이 어떻게 만들어지고 어떻게 합성되는지에 대한 정보를 완전히 가려줌(캡슐화)
무엇
이 생성되나요? → 알 수 없음
어떻게
생성되나요? → 알 수 없음
언제
생성되나요? → 알 수 없음
누가
이걸 생성하나요? → 알 수 없음
: 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴
하나의 클래스를 기반으로 단 하나의 인스턴스를 만들어, 이를 기반으로 로직을 만드는 데에 쓰임
생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴함
하나의 인스턴스를 만들어놓고, 해당 인스턴스를 다른 모듈들이 공유하여 사용하기 때문에 인스턴스 생성 비용이 감소됨
모듈 간의 결합을 강하게 만든다는 단점이 있음
💡 이러한 모듈 간의 결합을 조금 느슨하게 하기 위해 의존성 주입(Dependency Injection)이라는 개념을 사용할 수 있다.
보통 데이터베이스 연결 모듈(DBCP, DataBase Connection Pool)에 많이 사용함
(DB 연결 과정이 부하가 크고, 한 번 연결된 객체를 계속 사용해야 하기 때문)
스프링 컨테이너도 객체를 싱글톤으로 관리함
Java에서의 싱글톤 구현
class Singleton {
private static class singleInstanceHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return singleInstanceHolder.INSTANCE;
}
}
public class HelloWorld {
public static void main(String[] args) {
Singleton a = Singleton.getInstance();
Singleton b = Singleton.getInstance();
System.out.println(a.hashCode());
System.out.println(b.hashCode());
if (a == b) {
System.out.println(true);
}
}
}
JDBC에서 싱글톤을 활용하여 DB 연결하기
// 데이터베이스와 연결과 끊어주기위한 클래스
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConn {
private static Connection dbConn;
public static Connection getConnection() throws SQLException, ClassNotFoundException{
if (dbConn == null){
//dbConn이 null이면, 연결된 것이 없으니 연결해야한다.
String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe" ;
String user = "hr";
String pass = "12345";
Class. forName("oracle.jdbc.driver.OracleDriver");
dbConn = DriverManager.getConnection(url, user, pass);
}
return dbConn ;
}
//db와의 연결을 맺어주기 위한 메소드.
public static void close() throws SQLException {
if (dbConn != null){
if(!dbConn .isClosed()){
dbConn.close();
}
}
}
//db와의 연결을 끊어주는 메소드
}
// ex) 연결하기 예제
import java.sql.Connection;
public class jdbcTest {
public static void main(String[] args) {
try{
Connection conn = DBConn.getConnection ();
//정의한 DBConn 클래스로 손쉽게 연결.
System. out.println("오라클에 연결되었습니다." );
} catch(Exception e){
System. out.println(e.toString());
}
}
}
객체지향 프로그래밍의 핵심인 상속과 다형성을 해친다.
객체지향 프로그래밍의 또 다른 핵심인 정보 은닉을 해친다. 공유의 목적으로 생성된 클래스이기 때문에, 객체를 요청하는 메소드를 public으로 강제할 수밖에 없다.
Java의 고정적 싱글턴 패턴은 객체가 하나인 것을 보장할 수 없다.
💡 싱글턴 패턴을 사용할 땐 조심하자!
즉, 싱글턴 패턴은 굉장히 많이 활용되는 패턴이나, 앞서 말한 객체지향 프로그래밍의 기본 사상들을 많이 침해하기 때문에 굉장히 비판을 많이 받는 디자인 패턴이다.
따라서 싱글턴 패턴은 사용 시 매우 조심해서 사용해야 한다.
그것이 아니라면 위의 고전적인 싱글턴 패턴이 아닌 개선된 방식으로 객체의 싱글턴 방식을 구현하여 사용해야 한다.
: 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴
상속 관계에 있는 두 클래스에서, 상위 클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정함
상위 클래스와 하위 클래스가 분리되기 때문에 느슨한 결합을 가짐
상위 클래스에서는 인스턴스 생성 방식에 대해 전혀 알 필요가 없기 때문에, 더 많은 유연성을 가지게 됨
객체 생성 로직이 따로 떼어져 있기 때문에, 코드를 리팩터링하더라도 한 곳만 고칠 수 있게 됨 → 유지 보수성 증가
팩토리 메소드 패턴 : 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정하게 만든다. 즉 팩토리 메소드 패턴을 이용하면 클래스의 인스턴스를 만드는 일을 서브클래스에게 맡기는 것.
추상 팩토리 패턴 : 인터페이스를 이용하여 서로 연관된, 또는 의존하는 객체를 구상 클래스를 지정하지 않고도 생성.
Java에서의 팩토리 패턴 구현
추후 작성 예정
💡 Enum 타입
- 상수의 집합을 정의할 때 사용되는 타입
- 코드를 리팩터링할 때 해당 집합에 관한 로직 수정 시 이 부분만 수정하면 됨 : 큰 강점
: 대상 객체(subject)에 접근하기 전, 그 접근에 대한 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 하는 디자인 패턴
이를 통해 객체의 속성, 변환 등을 보안 / 데이터 검증 / 캐싱 / 로깅에 사용함
프록시 객체로 쓰이기도 하지만, 프록시 서버로도 활용함
: 어떠한 대상의 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 작업을 가로챌 수 있는 객체를 뜻함
자바스크립트에서 프록시 객체는 2개의 매개변수를 가짐
프록시 패턴이 녹아들어 있는 객체
target
: 프록시할 대상
handler
: 프록시 객체의 target 동작을 가로채서 정의할 동작들이 정해져 있는 함수
: 서버와 클라이언트 사이에서 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용프로그램
nginx : 비동기 이벤트 기반의 구조와 다수의 연결을 효과적으로 처리 가능한 웹 서버. nginx를 프록시 서버로 둬서 실제 포트를 숨길 수도 있고, 정적 자원을 gzip 압축하거나, 메인 서버 앞단에서의 로딩을 할 수도 있다.
프록시 서버를 통해, 익명 사용자의 직접적인 서버로의 접근을 차단하고, 간접적으로 한 단계를 더 거침으로써 보안성을 더욱 강화할 수 있다.
: 객체의 행위를 바꾸고 싶은 경우 '직접' 수정하지 않고 전략이라고 부르는 '캡슐화한 알고리즘'을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴. = 정책 패턴(Policy Pattern)
💡 컨텍스트
프로그래밍에서의 컨텍스트 : 상황, 맥락, 문맥을 의미하며, 개발자가 어떠한 작업을 완료하는 데 필요한 모든 관련 정보
: 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴
Twitter(트위터) : 주체가 포스팅을 올리게 되면 알림이 팔로워에게 감
Event-Driven System
MVC 패턴 : Model(=주체)에서 변경 사항이 생겨 update() 메서드로 View(=옵저버)에 알려주고, 이를 기반으로 Controller가 작동함
다음 포스팅은 아키텍처 패턴에 대해 마저 이야기해본다.