본문 바로가기
프로그래밍/디자인패턴

추상 팩토리(Abstract Factory) 패턴

by bantomak 2024. 4. 24.

🤔문제

예를 들어 가구 판매장을 위한 프로그램을 만들고 있다고 가정해 보자. 코드는 다음을 나타내는 클래스들로 구성된다.

 

  1. 관련 제품들로 형성된 패밀리(제품군), 예: Chair(의자) + Sofa(소파) + CoffeeTable(커피 테이블)
  2. 해당 제품군의 여러 가지 변형. 예를 들어 Chair(의자) + Sofa(소파) + CoffeeTable(커피 테이블) 같은 제품들은 Modern(현대식), Victorian(빅토리안), ArtDeco(아르데코 양식)와 같은 변형으로 제공될 수 있다.

이제 새로운 개별 가구 객체를 생성했을 때, 이 객체들이 기존의 같은 패밀리 내에 있는 다른 가구 객체들과 일치하는 변형을 가지도록 할 방법이 필요하다. 그 이유는 당신의 고객이 스타일이 일치하지 않는 가구 세트를 받으면 크게 실망할 수 있기 때문이다.

 

또, 가구 공급업체들은 카탈로그를 매우 자주 변경하기 때문에, 그들은 새로운 제품 또는 제품군(패밀리)을 추가할 때마다 기존 코드를 변경해야 하는 번거로움을 피하고 싶을 것이다.

 

😊해결책

추상 팩토리 패턴의 첫 번째 방안은 각 제품 패밀리에 해당하는 개별적인 인터페이스를 명시적으로 선언하는 것이다. 그다음, 제품의 모든 변형이 위 인터페이스를 따르도록 한다. 예를 들어, 모든 의자의 변형들은 Chair(의자) 인터페이스를 구현한다; 모든 커피 테이블 변형들은 CoffeeTable(커피테이블) 인터페이스를 구현한다. 등의 규칙을 명시한다.

 

다음 단계는 추상 팩토리 패턴을 선언하는 것이다. 추상 팩토리 패턴은 제품 패밀리 내의 모든 개별 제품들의 생성 메서드들이 목록화되어 있는 인터페이스이다.

다음은 제품 변형을 다룰 차례이다. 제품 패밀리의 각 변형에 대해 AbstractFactory 추상 팩토리 인터페이스를 기반으로 별도의 팩토리 클래스를 생성한다. 팩토리는 특정 종류의 제품을 반환하는 클래스이다. 예를 들어 ModernFurnitureFactory(현대식 가구 팩토리)에서는 다음 객체들만 생성할 수 있다. ModernChair, ModernSofa 및 ModernCoffeeTable.

 

클라이언트 코드는 자신에 해당하는 추상 인터페이스를 통해 팩토리들과 제품들 모두와 함께 작동해야 한다. 그래야 클라이언트 코드에 넘기는 팩토리의 종류와 제품 변형들을 클라이언트 코드를 손상하지 않으며 자유자재로 변경할 수 있다.

 

🏠구조

  1. 추상 제품들은 제품 패밀리를 구성하는 개별 연관 제품들의 집합에 대한 인터페이스들을 선언한다.
  2. 구상 제품들은 변형들로 그룹화된 추상 제품들의 다양한 구현들이다. 각 추상 제품은 주어진 모든 변형에 구현되어야 한다.
  3. 추상 팩토리 인터페이스는 각각이 추상 제품들을 생성하기 위한 여러 메서드들의 집합을 선언한다.
  4. 구상 팩토리들은 추상 팩토리의 생성 메서드들을 구현한다. 각 구상 팩토리는 제품들의 특정 변형들에 해당하며 해당 특정 변형들만 구성한다.

🔑구현방법

  1. 고유한 제품 유형들 대 변형 제품들을 나타내는 매트릭스를 매핑한다
  2. 모든 제품 변형들에 대한 추상 제품 인터페이스들을 선언한다. 그 후 모든 구상 제품 클래스들이 위 인터페이스들을 구현하도록 한다.
  3. 추상 팩토리 인터페이스를 모든 추상 제품들에 대한 생성 메서드들의 집합과 함께 선언한다.
  4. 각 제품 변형에 대해 각각 하나의 구상 팩토리 클래스 집합을 구현하라.
  5. 앱 어딘가에 팩토리 초기화 코드를 생성하자. 초기화 코드는 앱 설정 또는 현재 환경에 따라 구상 팩토리 클래스 중 하나를 인스턴스화해야 한다. 이 팩토리 객체를 제품을 생성하는 모든 클래스들에 전달하자.
  6. 코드를 검토해서 제품 생성자에 대한 모든 직접 호출을 찾자. 이 호출들을 팩토리 객체에 대한 적절한 생성 메소드에 대한 호출들로 교체하라.

😎예제 코드

using System;

public partial class Program
{
    public interface AbstractFactory
    {
        public IProduct CreateProductA();
        public IProduct CreateProductB();
    }

    public class ConcreateFactory : AbstractFactory
    {
        public IProduct CreateProductA()
        {
            return new AProduct();
        }

        public IProduct CreateProductB()
        {
            return new BProduct();
        }
    }

    public interface IProduct
    {
        void UsefulFunction();
    }

    public class AProduct : IProduct 
    {
        public void UsefulFunction()
        {
            Console.WriteLine("Useful function.");
        }
    }

    public class BProduct : IProduct
    {
        public void UsefulFunction()
        {
            Console.WriteLine("Useful function.");
        }
    }

    static void Main(string[] args)
    {
        Process(new ConcreateFactory());
    }

    public static void Process(AbstractFactory factory)
    {
        var concreteFactory = new ConcreateFactory();

        var newA = concreteFactory.CreateProductA();
        var newB = concreteFactory.CreateProductB();

        newA.UsefulFunction();
        newB.UsefulFunction();
    }
}

👍장단점

  • 팩토리에서 생성되는 제품들의 상호 호환을 보장할 수 있다.
  • 구상 제품들과 클라이언트 코드 사이의 단단한 결합을 피할 수 있다.
  • 단일 책임 원칙. 제품 생성 코드를 한 곳으로 추출하여 코드를 더 쉽게 유지보수할 수 있다.
  • 개방/폐쇄 원칙. 기존 클라이언트 코드를 훼손하지 않고 제품의 새로운 변형들을 생성할 수 있다.
  • 패턴과 함께 새로운 인터페이스들과 클래스들이 많이 도입되기 때문에 코드가 필요 이상으로 복잡해질 수 있다.

🔍다른 패턴관의 관계

  • 많은 디자인은 복잡성이 낮고 자식 클래스들을 통해 더 많은 커스터마이징이 가능한 팩토리 메서드로 시작해 더 유연하면서도 더 복잡한 추상 팩토리, 프로토타입 또는 빌더 패턴으로 발전해 나간다.
  • 빌더는 복잡한 객체들을 단계별로 생성하는 데 중점을 둔다. 추상 팩토리는 관련된 객체들의 패밀리들을 생성하는데 중점을 둔다. 추상 팩토리는 제품을 즉시 반환하지만 빌더는 제품을 가져오기 전에 당신이 몇 가지 추가 생성 단계들을 실행할 수 있도록 한다.
  • 추상 팩토리 클래스들은 팩토리 메서드들의 집합을 기반으로 하는 경우가 많다. 그러나 프로토타입을 사용하여 추상 팩토리의 구상 클래들의 생성 메서드들을 구현할 수도 있다.
  • 추상 팩토리는 하위 시스템 객체들이 클라이언트 코드에서 생성되는 방식만 숨기고 싶을 때 퍼사드 대신 사용할 수 있다.
  • 추상 팩토리브리지와 함께 사용할 수 있다. 이 조합은 브리지에 의해 정의된 어떤 추상화들이 특정 구현들과만 작동할 수 있을 때 유용하다. 이런 경우에 추상 팩토리는 이러한 관계들을 캡슐화하고 클라이언트 코드에서부터 복잡성을 숨길 수 있다.
  • 추상 팩토리들, 빌더들 및 프로토타입들은 모두 싱글턴으로 구현할 수 있다.

 

같이 보면 좋은 사이트

 

💠 추상 팩토리(Abstract Factory) 패턴 - 완벽 마스터하기

Abstract Factory Pattern 추상 팩토리 패턴은 연관성이 있는 객체 군이 여러개 있을 경우 이들을 묶어 추상화하고, 어떤 구체적인 상황이 주어지면 팩토리 객체에서 집합으로 묶은 객체 군을 구현화

inpa.tistory.com

참고 사이트

 

리팩터링과 디자인 패턴

Hello, world! Refactoring.Guru는 리팩토링, 디자인 패턴, SOLID 원칙 및 기타 스마트 프로그래밍 주제에 대해 알아야 할 모든 것을 쉽게 찾을 수 있는 자원입니다. 이 사이트에서는 이러한 모든 주제가 어

refactoring.guru

댓글