-
객체 생성 : 추상 팩토리 패턴 ( Abstract Factory Pattern )Programming/패턴 2020. 9. 4. 16:32
GOF의 디자인 패턴 중...
객체 생성의 추상 팩토리에 관한 내용
사용의도
- 구체적인 자식 클래스를 정의하지 않고 관련성을 갖는 객체들의 집합을 생성하거나 서로 독립적인 객체들의 집합을 생성할 수 있는 인터페이스를 제공하는 패턴.
동기
- UI 버튼 모양, 동작 방식이 서로 다르기 떄문에 직접 정의하여 사용하지 않고 인터페이스를 정의한 후, 인터페이스를 상속받은 클래스를 정의하여 구체적인 구현을 제공한다.
활용성
- 객체가 생성되거나 구성, 표현되는 방식과 무관하게 시스템을 독립적으로 만들고자 할 때 - ( 이해가 잘 안됨.. )
- 여러 제품군 중 하나를 선택해서 시스템을 설정해야 하고 한번 구성한 제품을 다른 것으로 대체할 수 있을 때
- 관련 제품 객체들이 함께 사용되도록 설계되었고 이 부분에 대한 제약이 외부에도 지켜지도록 하고 싶을 때
- 제품에 대한 클래스 라이브러리를 제공하고, 구현이 아닌 인터페이스를 노출시키고 싶을 때
구조
참여자
- AbstractFactory : 개념적 제품에 대한 객체를 생성하는 연산으로 인터페이스를 정의한다. ( 기아 자동차 )
- ConcreteFactory ( 1, 2 ) : 구체적인 제품에 대한 객체를 생성하는 연산으로 구현. ( 기아 자동차의 공장 )
- AbstractProduct ( A, B ) : 개념적 제품 객체에 대한 인터페이스를 정의한다. ( SUV, 승용차 )
- ConcreteProduct ( A1, A2, B1, B2 ) : 구체적으로 팩토리가 생성할 객체를 정의하고, AbstractProduct가 정의하는 인터페이스를 구현한다. ( 쏘렌토, K7 등등 )
- Client : AbstractFactory와 AbstractProduct 클래스에 선언된 인터페이스를 사용한다. ( 운전자 )
결과
- 구체적인 클래스를 분리
- 제품군을 쉽게 대체할 수 있음.
- 제품 사이의 일관성 증대
- 새로운 종료의 제품을 제공하기 어려움.
구현
- 팩토리를 단일체로 정의
- 제품을 생성
- 확장 가능한 팩토리들을 정의
예시코드
http://refactoring.guru/design-patterns/abstract-factory/cpp/example
/** * Each distinct product of a product family should have a base interface. All * variants of the product must implement this interface. */ class AbstractProductA { public: virtual ~AbstractProductA(){}; virtual std::string UsefulFunctionA() const = 0; }; /** * Concrete Products are created by corresponding Concrete Factories. */ class ConcreteProductA1 : public AbstractProductA { public: std::string UsefulFunctionA() const override { return "The result of the product A1."; } }; class ConcreteProductA2 : public AbstractProductA { std::string UsefulFunctionA() const override { return "The result of the product A2."; } }; /** * Here's the the base interface of another product. All products can interact * with each other, but proper interaction is possible only between products of * the same concrete variant. */ class AbstractProductB { /** * Product B is able to do its own thing... */ public: virtual ~AbstractProductB(){}; virtual std::string UsefulFunctionB() const = 0; /** * ...but it also can collaborate with the ProductA. * * The Abstract Factory makes sure that all products it creates are of the * same variant and thus, compatible. */ virtual std::string AnotherUsefulFunctionB(const AbstractProductA &collaborator) const = 0; }; /** * Concrete Products are created by corresponding Concrete Factories. */ class ConcreteProductB1 : public AbstractProductB { public: std::string UsefulFunctionB() const override { return "The result of the product B1."; } /** * The variant, Product B1, is only able to work correctly with the variant, * Product A1. Nevertheless, it accepts any instance of AbstractProductA as an * argument. */ std::string AnotherUsefulFunctionB(const AbstractProductA &collaborator) const override { const std::string result = collaborator.UsefulFunctionA(); return "The result of the B1 collaborating with ( " + result + " )"; } }; class ConcreteProductB2 : public AbstractProductB { public: std::string UsefulFunctionB() const override { return "The result of the product B2."; } /** * The variant, Product B2, is only able to work correctly with the variant, * Product A2. Nevertheless, it accepts any instance of AbstractProductA as an * argument. */ std::string AnotherUsefulFunctionB(const AbstractProductA &collaborator) const override { const std::string result = collaborator.UsefulFunctionA(); return "The result of the B2 collaborating with ( " + result + " )"; } }; /** * The Abstract Factory interface declares a set of methods that return * different abstract products. These products are called a family and are * related by a high-level theme or concept. Products of one family are usually * able to collaborate among themselves. A family of products may have several * variants, but the products of one variant are incompatible with products of * another. */ class AbstractFactory { public: virtual AbstractProductA *CreateProductA() const = 0; virtual AbstractProductB *CreateProductB() const = 0; }; /** * Concrete Factories produce a family of products that belong to a single * variant. The factory guarantees that resulting products are compatible. Note * that signatures of the Concrete Factory's methods return an abstract product, * while inside the method a concrete product is instantiated. */ class ConcreteFactory1 : public AbstractFactory { public: AbstractProductA *CreateProductA() const override { return new ConcreteProductA1(); } AbstractProductB *CreateProductB() const override { return new ConcreteProductB1(); } }; /** * Each Concrete Factory has a corresponding product variant. */ class ConcreteFactory2 : public AbstractFactory { public: AbstractProductA *CreateProductA() const override { return new ConcreteProductA2(); } AbstractProductB *CreateProductB() const override { return new ConcreteProductB2(); } }; /** * The client code works with factories and products only through abstract * types: AbstractFactory and AbstractProduct. This lets you pass any factory or * product subclass to the client code without breaking it. */ void ClientCode(const AbstractFactory &factory) { const AbstractProductA *product_a = factory.CreateProductA(); const AbstractProductB *product_b = factory.CreateProductB(); std::cout << product_b->UsefulFunctionB() << "\n"; std::cout << product_b->AnotherUsefulFunctionB(*product_a) << "\n"; delete product_a; delete product_b; } int main() { std::cout << "Client: Testing client code with the first factory type:\n"; ConcreteFactory1 *f1 = new ConcreteFactory1(); ClientCode(*f1); delete f1; std::cout << std::endl; std::cout << "Client: Testing the same client code with the second factory type:\n"; ConcreteFactory2 *f2 = new ConcreteFactory2(); ClientCode(*f2); delete f2; return 0; }
반응형'Programming > 패턴' 카테고리의 다른 글
객체 생성 : 프로토타입 패턴 ( Prototype Pattern ) (0) 2020.09.26 UML 관계 종류 (0) 2020.09.22 객체 생성 : 빌더 패턴 ( Builder Pattern ) (0) 2020.09.22 객체 생성 : 싱글턴 패턴 ( Singleton Pattern ) (0) 2020.05.04 객체 행동 : 전략 패턴 ( Strategy Pattern ) - 정책(Policy) (0) 2020.05.04