Design Pattern

디자인 패턴이란?

자주 사용하는 설계 패턴을 정형화한 것

GOF(Gang Of Four) 디자인 패턴

소프트웨어 설계 경험을 바탕으로 정리한 디자인 패턴을 정리한 것. 총 23개의 디자인 패턴이 있다.

디자인 패턴 Pros vs Cons

  • Pros
  1. 개발자간의 원활한 소통
  2. 소프트웨어 구조 파악이 용이
  3. 재사용을 통한 개발 시간 단축
  4. 설계 변경 요청에 대한 유연한 대처
  • Cons
  1. 객체지향 설계/구현 : 설계 및 구현에 대한 이해 필요
  2. 초기 투자 비용 부담 : 초기 설계 시간/비용적 부담

생성 패턴 (5/23)

객체를 생성하는 것과 관련된 패턴, 객체의 생성과 변경이 전체 시스템에 미치는 영향을 최소화 하고, 코드의 유 연성을 높여준다.

  • Factory Method
  • Singleton
  • Prototype
  • Builder
  • Abstract Factory
  • Chaining : (GOF 아님, Lombok의 기반패턴)

구조 패턴 (7/23)

프로그램 내의 자료구조나 인터페이스 구조 등 프로그램 구조를 설계하는데 활용될 수 있는 패턴 클래스, 객체들 의 구성을 통해 더 큰 구조를 만들 수 있게 해준다.
큰 규모의 시스템에서는 많은 클래스들이 서로 의존성을 가지게 되는데, 이런 복잡한 구조를 개발하기 쉽게 만들 어 주고, 유지보수하기 쉽게 만들어 준다.

  • Adapter
  • Composite
  • Bridge
  • Decorator
  • Facade
  • Flyweight
  • Proxy

행위 패턴 (11/23)

반복적으로 사용되는 객체들의 상호작용을 패턴화한 것. 상호작용 및 책임분산방법을 제공한다.

  • Template Method
  • Interpreter
  • Iterator
  • Observer
  • Strategy
  • Visitor
  • Chain of responsibility
  • Command
  • Mediator
  • State
  • Memento

이 중, 7개정도의 패턴을 알아보도록 한다.

Singleton Pattern

  • Singleton 패턴은 어떤 클래스 혹은 객체가 유일하게 1개만 존재해야 할 때 사용한다.

이를 주로 사용하는 곳은 서로 자원을 공유할 때 사용하는데, TCP Socket통신에서 Connect객체에 주로 사용 한다. 스프링에서는 Bean이 싱글톤 객체에 해당한다.

소켓통신 클라이언트 예를 만들면서 보자.

public class SocketClient {

  private SocketClient socketClient;

  private SocketClient() {

  }

  public static SocketClient getInstance(){
    if(socketClient == null){(
      socketClient = new SocketClient();
    }
    return socketClient;
  }

  public void connect() {
    System.out.println("connect");
  }
}

싱글톤은 자기자신을 객체로 가지고 있고, 외부에서 getInstance()메소드를 통해 단 하나만 존재하는 객체에 접글할 수 있도록 해야한다. (L3)

싱글톤 객체는 단 하나만 존재해야하므로 외부에서 생성할 수 없어야 한다. 따라서 private 키워드로 생성자를 제한해둔다.(L5)

외부에서는 단하나의 객체를 getInstance() 메소드로만 접근할 수 있게 static키워드로 선언해둔다.(L9)

getInstance()메소드 내에서는 싱글톤 객체가 null인지 체크하고, null이라면 새 인스턴스를 만들어서 리 턴 하도록 한다. (L10)

이제 싱글톤 클래스는 완성이 되었고, 다른 클래스에서 싱글톤 객체에 접근해서 사용할때에는 어떻게 하는지 알아 보자.

public class A {

  private SocketClient socketClient;

  public A() {
    this.socketClient = SocketClient.getInstance();
  }

  public SocketClient getSocketClient() {
    return this.socketClient;
  }
}

일단 A클래스에서 싱글톤객체를 받아서 사용할 멤버변수를 선언해주고(L3), A클래스가 생성될때 싱글톤 클래스로 부터 싱글톤 객체를 받아 A클래스의 멤버변수에 동치시켜준다.(L5)

그리고 A클래스 외부에서 A클래스의 객체로부터 싱글톤 객체를 받아 사용할수 있게 하려면 싱글톤 객체의 타입으 로 getter를 만들어준다.(L9)

Adapter Pattern

호환성이 없는 기존 클래스의 인터페이스를 변환하여 재사용 할 수 있도록 한다. SOLID 원칙 중에서, 개방폐쇄 원칙(OCP)를 따른다.

110V를 220V로 바꾸는 돼지코예제를 통해 배워보자.

public interface Electronic110V {

  void powerOn();

}
public interface Electronic220V {

  void connect();

}
public class HairDryer implements Electronic110V {

  @override
  public void powerOn() {
    System.out.println("헤어드라이기가(110V) 켜졌습니다.");
  }
}
public class AirConditioner implements Electronic220V {

  @override
  public void connect() {
    System.out.println("에어컨(220V)이 켜졌습니다.");
  }
}
//main 클래스

public static void main() {

  HairDryer hairDryer = new HairDryer();
  connect(hairDryer);

  AirConditioner airConditioner = new AirConditioner();
  //connect(airConditioner); 타입이 맞지 않아 에러. 변환필요.

  //어댑터를 사와서 꽂아주자. 아래 어댑터 클래스 정의되어있다.
  Electronic110V adapter = new Adapter(airConditioner);
  connect(adapter);

}

//110V만 받아서 사용할 수 있는 메소드(콘센트) 생성
public static void connect(Electronic110V electronic110V){
  electronic110V.powerOn();
}
public class Adapter implements Electronic110V {

  private Electronic220V electronic220V;

  public Adapter(Electronic220V electronic220V){
    this.electronic220V = electronic220V;
  }

  @override
  public void powerOn() {
    electronic220V.connect();
  }
}

즉, adapter패턴은 서로 다른 객체의 타입을 호환되도록 하나의 추가적인 클래스를 통해 호환되도록 해주는 것 이다.