팩터리 메서드 패턴 (Factory Method Pattern)

Jane·2021년 2월 16일
0

팩터리 메서드 패턴

  • 팩터리는 객체를 생성하는 공장이고 팩터리 메서드는 객체를 생성 반환하는 메서드이다.
  • 의존관계 역전 원칙(Dependency Inversion Principle)을 활용한다.
    → 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존관계를 역전시킴으로써 상위 계층을 하위 계층의 구현으로부터 독립시켰다.
    • High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces).
    • Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

장점

  1. 생성자와 달리 이름을 가질 수 있다.
    • 어떤 객체가 반환되고, 해당 메소드가 어떠한 행동을 갖고 있는지 파악하기 쉽다.
  2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.
  3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
public class MyBook {
    public MyBook() {
    }

    public static MyBook getChildInstance() {
        return MyBookChild.getInstance();
    }
}

public class MyBookChild extends MyBook {
    private MyBookChild() {
    }

    public static MyBookChild getInstance() {
        return new MyBookChild();
    }
}
  1. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");
        
        // 원소의 수에 따라 다른 하위 클래스의 인스턴스 반환
        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }
  1. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.

단점

  1. 상속을 하려면 public이나 protected 생성자가 필요하니 정적 팩토리 메서드만 제공하면 하위 클래스를 만들 수 없다.
  2. 생성자처럼 API에 명확히 드러나지 않기 때문에 인스턴스를 생성하기 위해서는 프로그래머가 정적 팩터리 메서드의 활용법을 알아내야 한다.

구현

public abstract class Animal {
    // 추상 팩터리 메서드
    abstract AnimalToy getToy();
}

public abstract class AnimalToy {
    abstract void identify();
}

public class Cat extends Animal {
    // 추상 팩터리 메서드 오버라이딩
    @Override
    AnimalToy getToy() {
        return new CatToy();
    }
}

//팩터리 메서드가 생성할 객체
public class CatToy extends AnimalToy {
    @Override
    public void identify() {
        System.out.println("cat toy");
    }
}

public class Dog extends Animal {
    // 추상 팩터리 메서드 오버라이딩
    @Override
    AnimalToy getToy() {
        return new DogToy();
    }
}

//팩터리 메서드가 생성할 객체
public class DogToy extends AnimalToy {
    public void identify() {
        System.out.println("dog toy");
    }
}

public class Driver {
    public static void main(String[] args) {
        // 팩터리 메서드를 보유한 객체들 생성
        Animal dog = new Dog();
        Animal cat = new Cat();

        // 팩터리 메서드가 반환하는 객체들
        AnimalToy dogToy = dog.getToy();
        AnimalToy catToy = cat.getToy();

        // 팩터리 메서드가 반환한 객체들을 사용
        dogToy.identify();
        catToy.identify();
    }
}

Source

5개의 댓글