본문 바로가기
Design Pattern

[Design Pattern] Singleton 패턴 / Factory 패턴

by happy coding! 2019. 6. 13.
반응형

디자인 패턴이란?

  • 일반적인 설계 문제를 해결하기 위하여 짜여진 상호 협력하는 객체들과 클래스들에 대한 기술 (GoF)
  • 자주 발생하는 설계상의 문제를 해결하기 위한 반복적인 해법 (Smalltalk Companion)
  • 반복되는 구조를 설계할 때 설계를 재활용하는데 초점을 두는데 비하여 프레임워크는 세부 설계와 구현에 초점을 두고 있다. (Coplien & Schmidt)

생성 패턴

  • Singleton pattern
  • Factory pattern
    • Simple factory pattern
    • Factory method pattern
    • Abstract factory pattern
  • Builder pattern
  • Prototype pattern
  • Object pool pattern

Singleton pattern

  • 매우 간단하고 매우 자주 사용됨
  • 클래스에 오직 하나의 객체만이 생성됨을 보장
  • 오직 하나의 인스턴스만을 생성하여 이를 접근하는 메소드를 제공
  • 특정 객체를 인스턴스로 만드는데 사용되는 방법
    • 객체가 인스턴스로 이미 생성되었는지 체크하여
    • 그렇다면, 이미 만들어진 객체의 레퍼런스를 리턴
    • 그렇지 않다면, 객체를 만들고 그 객체의 레퍼런스를 리턴
    • 생성자는 protect 또는 private 으로 선언
/* Singleton pattern */
public class Singleton {

    // 생성자 호출되지 않도록 private으로 
    private static Singleton instance;

    private Singleton() {
        System.out.println("객체 생성됨");
    }
    // new Singleton().getInstance() -> Singleton 객체 반환 
    public static Singleton getInstance() {
        if (instance == null)
            instance = new Singleton();
        return instance;
    }

    // 객체.doSomething()
    public void doSomething() {
        System.out.println("Something is Done.");
    }
}
public class Client {

    public static void main(String[] args) {

        // Singleton s1 = new Singleton();
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();

        if (s1 == s2)
            System.out.println("동일함");
        else 
            System.out.println("다름");

        s1.doSomething();
    }

}
  • 이전 경우 싱글 쓰레딩에서는 문제 없지만 멀티쓰레딩인 경우 문제가 발생할 수 있다.
public static synchronized Singleton getInstance() {
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
  • 위의 경우 불필요하게 delay가 발생

  • Synchronized singleton with double-checked locking mechanism

    • instance null check 가 2번 되어야함.

      // double check
      public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null)
                    instance = new Singleton();
            }
        }
        return instance;
      }
  • Lock(Block)을 임의로 처리하지 않고도 해결할 수 있을까?

    • java static은 Class Load가 딱 한번만 일어남을 보장
  • Lock-free thread-safe singleton

  • java에 한해서는 static을 사용할 수 있다.

    public class Singleton {
    
      // TODO
      private static Singleton instance = new Singleton();
    
      private Singleton() {
          System.out.println("객체 생성됨");
      }
    
      public static Singleton getInstance() {
          return instance;
      }
    
      public void doSomething() {
          System.out.println("Something is Done.");
      }
    }
  • Early and lazy loading

  • lazy loading: getInstance 호출 시 Instance 생성. 즉 필요시 생성하여 메모리 효율화


Factory Pattern

Vehicle bike = new Bike();
Vehicle car = new Car();

  • 위와 같이 객체를 생성한다면 어떤 문제가 있을까?

    • the open/closed principle 위반
    • 신규 class(Bike, Van)가 추가될 때마다 main code 수정 필요
    • the single responsibility principle 위반
  • 생성 책임을 별도로 분리

  • Simple factory pattern

    • SimpleFactory 클래스가 제품1과 제품2 instance를 생성하는 책임을 진다.
    • Client가 객체 필요시, createProduct()를 호출한다.
public class VehicleFactory {

    // TODO
    public enum VehicleType {
        Bike, Car, Truck
    }

    public static Vehicle create(VehicleType type) {
        if (type.equals(VehicleType.Bike))
            return new Bike();
        else if (type.equals(VehicleType.Car)) 
            return new Car();
        else if (type.equals(VehicleType.Truck))
            return new Truck();
        else 
            return null;
    }

}
public class Client {

    public static void main(String[] args) {

        // TODO
        Vehicle bike = VehicleFactory.create(VehicleType.Bike);
        bike.doSomething();

        Vehicle car = VehicleFactory.create(VehicleType.Car);
        car.doSomething();
    }

}
  • Factory pattern - Factory method pattern

    • Simple Factory를 개선

      • factory class를 추상화로 만들고
      • factory class를 구상화한 subclass에서 상세 제품 instance 생성 코드 작성
    • 객체 생성을 서브 클래스에 위임

    • 자동차 종류 특색에 맞는 Factory 필요. 하지만 모든 자동차 공장마다 생산 공정시 품질을 일정하게 유지하기 위해 공통적인 공정은 본사에서 지정

      • 자동차를 주문하면 Sport Car와 SedanCar 공장에서 특징에 맞게 자동차를 생산
      • 본사 규정에 따라 모두 테스트와 도색은 본사 규정대로 실시
      • 이후 고객에게 생산된 자동차를 전달
  • Anonymous concreate factory

    • 구상 객체를 별도 만들지 않고, Client Code에 Anonymous class를 이용하여 생성
  • Factory method pattern : 조건에 따른 객체 생성을 팩토리 클래스로 위임하여, 팩토리 클래스에서 객체를 생성하는 패턴

  • Abstract factory pattern

    • 서로 관련이 있는 객체들을 통째로 묶어서 팩토리 클래스로 만들고, 이를 팩토리를 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성하는 패턴
  • Factory pattern

    • Simple factory: 객체 생성을 별도로 위임
    • Factory method : 객체 생성을 서브 클래스에 위임
    • Abstract factory : 의존 객체의 패밀리를 생성하기 위함
반응형

댓글