[디자인패턴] 생성 패턴 - 추상 팩토리(Abstract Factory) 패턴
*추상 팩토리 패턴
- 서로 관련있는 여러 객체를 만들어주는 인터페이스
- 구체적으로 어떤 클래스의 인스턴스를(concrete product)를 사용하는지 감출 수 있다. (클라이언트에서 사용하는 인스턴스를 만들어 쓰는 코드를 인터페이스로 추상화한다)
- 구체적인 팩토리에서 구체적인 인스턴스를 만드는 부분은 팩토리 메소드 패턴과 비슷하지만 초점은 팩토리를 사용하는 클라이언트에 맞춰져 있다.
- Product(Factory Method)
package me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice;
import lombok.Getter;
import lombok.Setter;
import me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.Oxidizer;
import me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.Tonic;
@Getter @Setter
public class HairDye {
...
private DarkOxidizer oxidizer;
private DarkTonic tonic;
...
}
기존의 구현체에 필요한 데이터 필드를 추가한다.
- ConcreateProductA, ConcreateProductB
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkOxidizer{
}
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkTonic{
}
추가된 구현체에 대한 클래스를 만든다.
- ConcreteCreator(Factory Method)
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.DarkHairDye;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.DefaultHairDesigner;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.HairDye;
public class DarkHairDesigner extends DefaultHairDesigner {
@Override
public HairDye dyingService() {
HairDye hairDye = new DarkHairDye();
hairDye.setOxidizer(new DarkOxidizer());
hairDye.setTonic(new DarkTonic());
return hairDye;
}
}
팩토리(creator)에 구현체에 추가된 Oxidizer나 Tonic를 구현하기 위해서 현재는 new 키워드를 통해 직접적으로 구현하는데, 추상 팩토리 패턴으로 클라이언트 측에서 사용하는 구현체에 따라 인스턴스가 정해지도록 한다.
- Abstract Factory
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public interface HairDyeProducts {
Oxidizer useOxidizer();
Tonic useTonic();
}
추상 팩토리 패턴으로 만들 인터페이스를 정의한다. 이 부분엔 추가되는 구현체(Product)를 정의한다.
- ProductA, ProductB
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public interface Oxidizer {
}
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public interface Tonic {
}
추상 팩토리에서 사용될 구현체(Product)의 인터페이스를 정의한다.
- ConcreteProductA, ConcreteProductB
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkOxidizer implements Oxidizer{
}
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkTonic implements Tonic{
}
인터페이스로 정의된 구현체를 구체적인 클래스를 정의한다.
- ConcreteFactory
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkHairDyeProducts implements HairDyeProducts{
@Override
public Oxidizer useOxidizer() {
return new DarkOxidizer();
}
@Override
public Tonic useTonic() {
return new DarkTonic();
}
}
추상 팩토리를 구현할 구현 클래스를 정의한다.
- ConcreteCreator(Factory Method)
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.DarkHairDye;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.DefaultHairDesigner;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.HairDye;
public class DarkHairDesigner extends DefaultHairDesigner {
private HairDyeProducts hairDyeProducts;
public DarkHairDesigner(HairDyeProducts hairDyeProducts) {
this.hairDyeProducts = hairDyeProducts;
}
@Override
public HairDye dyingService() {
HairDye hairDye = new DarkHairDye();
hairDye.setOxidizer(hairDyeProducts.useOxidizer());
hairDye.setTonic(hairDyeProducts.useTonic());
return hairDye;
}
}
기존 DarkHariDesigner에서 Oxidizer나 Tonic을 정의 하려면 new 인스턴스를 사용하기 때문에 의존성이 강하게 결합되어 있었지만, HairDyeProducts 인터페이스를 통해서 의존성의 결합을 느슨하게 변경했다.
추가적으로 형태는 같지만 다른 기능을 하는 클래스를 추가하는 경우,
- ConcreteProductC, - ConcreteProductD
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkExOxidizer implements Oxidizer{
}
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkExTonic implements Tonic{
}
다른 구현체(Product)를 추가한다.
- ConcreteFactory
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
public class DarkHairDyeExProducts implements HairDyeProducts{
@Override
public Oxidizer useOxidizer() {
return new DarkExOxidizer();
}
@Override
public Tonic useTonic() {
return new DarkExTonic();
}
}
추상 팩토리를 구현하는 또 다른 구현체를 정의한다.
- Product(Factory Method)
package me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice;
import lombok.Getter;
import lombok.Setter;
import me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.Oxidizer;
import me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.Tonic;
@Getter @Setter
public class HairDye {
...
private Oxidizer oxidizer;
private Tonic tonic;
...
}
기존에 DarkOxidizer, DarkTonic 등의 클래스 타입으로 되어있는 부분을 느슨한 결합을 위해 인터페이스 타입으로 수정한다.
- Client
package me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.HairDesigner;
import me.whiteship.designpatterns._01_creational_patterns._02_factory_method.practice.HairDye;
public class Client {
public static void main(String[] args) {
HairDesigner hairDesigner = new DarkHairDesigner(new DarkHairDyeProducts());
HairDesigner hairDesigner = new DarkHairDesigner(new DarkHairDyeExProducts());
HairDye hairDye = hairDesigner.dyingService();
System.out.println(hairDye.getOxidizer().getClass());
System.out.println(hairDye.getTonic().getClass());
// class me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.DarkOxidizer
// class me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.DarkTonic
// class me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.DarkExOxidizer
// class me.whiteship.designpatterns._01_creational_patterns._03_abstract_factory.practice.DarkExTonic
}
}
클라이언트에서 구조는 같지만 비슷한 형태의 인스턴스를 변경하기만 하면 다른 결과 값을 얻을 수 있다.
팩토리 메소드 패턴과 추상 팩토리 패턴은 비슷하다. 이 두가지는 관점의 차이이다. 팩토리 메소드 패턴은 객체 또는 인스턴스를 만드는(구현하는) 과정에 관점이 집중이 되어있고, 추상 팩토리 패턴은 팩토리를 사용하는 쪽(클라이언트)의 관점에 집중하여 보고있다.
- 팩토리 메소드 패턴: 구체적인 객체 생성 과정을 하위 또는 구체적인 클래스로 옮기는게 목적
- 추상 팩토리 패턴: 관련있는 여러 객체를 구체적인 클래스에 의존하지 않고 만들 수 있게 하는것이 목적
https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4
'디자인패턴' 카테고리의 다른 글
[디자인패턴] 생성 패턴 - 프로토타입(Prototype) 패턴 (0) | 2022.08.23 |
---|---|
[디자인패턴] 생성 패턴 - 빌더(Builder) 패턴 (0) | 2022.08.23 |
[디자인패턴] 생성 패턴 - 팩토리 메소드(Factory method) 패턴 (0) | 2022.08.23 |
[디자인패턴] 생성 패턴 - 싱글톤(Singleton) 패턴 (0) | 2022.08.23 |