ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] Singleton 패턴 / Factory 패턴
    Computer Science/Design Pattern 2019. 6. 13. 11:55
    반응형

    디자인 패턴이란?

    • 일반적인 설계 문제를 해결하기 위하여 짜여진 상호 협력하는 객체들과 클래스들에 대한 기술 (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 : 의존 객체의 패밀리를 생성하기 위함
    반응형
Designed by Tistory.