추상 공장 디자인 패턴이 필요한 이유는 무엇입니까?


124

대부분의 정의는 다음과 같이 말합니다.

추상 팩토리는 구체적인 클래스를 지정하지 않고 관련 객체의 패밀리를 생성하기위한 인터페이스를 제공합니다.

구체적인 클래스 자체의 객체를 생성하여 작업을 수행 할 수 있으므로 Abstract Factory Pattern의 용도는 무엇입니까? Concrete 클래스의 객체를 생성하는 팩토리 메소드가있는 이유는 무엇입니까?

abstractFactory 패턴을 구현해야하는 실제 예제를 제공 해주세요.

답변:


218

6
이러한 모든 예제는 단일 제품 인터페이스를 반환하기 때문에 Factory Method Pattern을 설명합니다. 이들 중 어떤 것도 관련 제품 인터페이스 제품군을 생성하지 않기 때문에 추상 팩토리 패턴이 아닙니다.
jaco0646

32
완전한 공개를 위해이 답변의 저자는 연결된 모든 답변의 저자이기도 함을 분명히 했어야합니다. 따라서이 목록은 SO 커뮤니티의 대표적인 샘플 이 아닙니다 .
jaco0646

1
@ jaco0646 IIRC, Factory Method 패턴 은 상속에 의존 하는 Template Method 패턴 의 전문화입니다 . 하지만 현재 여행 중이고 GoF 책을 가지고 있지 않기 때문에 착각 할 수 있습니다. "그들 중 어느 것도 관련 제품 인터페이스 제품군을 생성하지 않는다"는 의미는 무엇입니까?
마크 시만

1
공장이 추상 공장 패턴을 따르지 않음을 나타내는 가장 간단한 단서는 공장이 생산하는 추상 제품을 세는 것입니다 ( "추상"이라는 단어의 남용을 피하기 위해 "추상 제품"대신 "제품 인터페이스"라는 용어를 사용했습니다). . 단일 추상 제품을 생산하는 팩토리는 추상 팩토리가 될 수 없습니다. 정의에 따라 Abstract Factory는 관련 제품 제품군을 생산하기 때문 입니다 . 이 제품군 은 하나의 인터페이스의 서로 다른 구현을 참조하는 것이 아니라 서로 다른 관련 인터페이스를 가진 제품을 참조하는 것이 중요합니다 .
jaco0646

1
다음은 oodesign.com/abstract-factory-pattern.html 예제 입니다 . 이것이 원래 추상 팩토리 패턴이 만들어진 것입니다.
user2802557

23

Abstract Factory 패턴 사용에 대한 실제 사례는 두 가지 다른 데이터 소스에 대한 데이터 액세스를 제공하는 것입니다. 애플리케이션이 다른 데이터 저장소를 지원한다고 가정합니다. (예 : SQL 데이터베이스 및 XML 파일). 당신은 두 개의 서로 다른 데이터 액세스 인터페이스가를 예 가지고 IReadableStoreIWritableStore관계없이 사용되는 데이터 소스 유형의 응용 프로그램에서 예상되는 일반적인 방법을 정의.

어떤 유형의 데이터 소스를 사용하더라도 클라이언트 코드가 데이터 액세스 클래스를 검색하는 방식을 변경해서는 안됩니다. 귀하는 AbstractDataAccessFactory데이터 소스의 종류가 구성된 알고 및 제공 콘크리트 공장을 클라이언트 코드, 즉 SqlDataAccessFactoryXmlDataAccessFactory. 이러한 콘크리트 팩토리는 구체적인 구현을 만들 수 있습니다 (예 : SqlReadableStoreSqlWriteableStore.

.NET Framework 의 DbProviderFactory 가이 패턴의 예입니다.


18
이 답변은 Factory Method 패턴 또는 Static Factory 패턴을 정확하게 설명 할 수 있지만 Abstract Factory 패턴은 설명 할 수 없습니다.
jaco0646

5

내가 당신을 옳게 이해한다면-질문은 왜 우리가 Factory 메서드와 추상 팩토리 패턴을 모두 가지고 있는가입니다. 다른 다형성 클래스가 다른 인스턴스화 절차를 가질 때 추상 팩토리가 필요합니다. 그리고 어떤 모듈이 객체 초기화의 세부 사항을 알지 못해도 인스턴스를 만들고 사용하기를 원합니다. 예를 들어, 일부 계산을 수행하는 Java 객체를 생성하려고합니다. 그러나 그들 중 일부는 응용 프로그램의 일부이며 다른 바이트 코드는 DB에서 읽어야합니다. 다른 한편, 왜 우리는 공장 방법이 필요한가? 그 추상적 인 공장이 그것과 겹치는 것에 동의하십시오. 그러나 어떤 경우에는 작성하는 코드가 훨씬 적고 클래스와 인터페이스가 적 으면 시스템을 더 쉽게 이해할 수 있습니다.


4

구체적인 클래스 자체의 객체를 생성하여 작업을 수행 할 수 있으므로 Abstract Factory Pattern의 용도는 무엇입니까? Concrete 클래스의 객체를 생성하는 팩토리 메소드가있는 이유는 무엇입니까?

Abstract Factory가 없는 경우 Client는 구체적인 클래스의 세부 사항을 알아야합니다. 이 긴밀한 결합은 Abstract Factory 에서 제거되었습니다 .

이제 Factory Method 는 클라이언트가 사용해야하는 계약을 노출합니다. Factory Method에 의해 노출 된 인터페이스를 구현하는 신제품을 추가하여 공장에 더 많은 제품을 추가 할 수 있습니다.

더 나은 이해를 위해 다음과 같은 관련 SE 질문을 참조하십시오.

팩토리 패턴과 추상 팩토리 패턴의 기본적인 차이점은 무엇입니까?

의지:

구체적인 클래스를 지정하지 않고 관련되거나 종속 된 개체의 패밀리를 만들기위한 인터페이스를 제공합니다.

당신은 이해할 수있다 소스 작성 기사에서 Abstract Factory 패턴의 의도, 구조, 체크리스트 및 경험 규칙을.

체크리스트 :

  1. 플랫폼 독립성 및 생성 서비스가 현재 고통의 원인 인지 결정합니다 .
  2. 매트릭스를 매핑 플랫폼제품 .
  3. 제품 별 팩토리 메소드로 구성된 팩토리 인터페이스 를 정의하십시오 .
  4. 새 연산자에 대한 모든 참조를 캡슐화하는 각 플랫폼에 대한 팩토리 파생 클래스를 정의합니다 .
  5. 클라이언트는 새에 대한 모든 참조를 은퇴하고 사용해야 팩토리 메소드를 작성하기 위해 제품 객체.

2

Abstract Factory는 코드 기반을 통합하면서 여러 플랫폼을 지원하는 데 적합합니다. Windows, Linux 및 OSX에서 실행하려는 대형 Qt 또는 GTK + 또는 .NET / Mono 프로그램이 있다고 가정합니다. 그러나 각 플랫폼에서 다른 방식으로 구현되는 기능이 있습니다 (아마도 kernel32 API 또는 POSIX 기능을 통해).

public abstract class Feature
{
    public abstract int PlatformSpecificValue { get; }

    public static Feature PlatformFeature
    {
        get
        {
            string platform;
            // do platform detection here
            if (platform == "Win32")
                return new Win32Feature();
            if (platform == "POSIX")
                return new POSIXFeature();
        }
    }

    // platform overrides omitted
}

이 Abstract Factory를 사용하면 UI가 현재 플랫폼에 대해 알 필요가 없습니다.

Feature feature = Feature.PlatformFeature;
Console.WriteLine(feature.PlatformSpecificValue);

1
이해가 안되는데, 팩토리 메서드를 사용하여 추상 유형을 반환하여 클라이언트가 구현 세부 정보를 알지 못하도록하는 것과 어떻게 다른가요?
kiwicomb123

1

디자인 패턴을 보면 거의 모든 패턴이 중복 될 수 있습니다. 그러나 어떤 패턴이 유사한 유형의 문제에 대한 솔루션을 위해 일반적으로 사용되는 접근 방식을 의미하는지. 디자인 패턴은 유사한 유형의 디자인 문제에 대한 디자인 수준 접근 방식 또는 솔루션을 제공합니다. 디자인 패턴을 사용하면 문제를 해결하고 더 빨리 제공 할 수 있습니다.



1

Abstract Factory 패턴이 과대 평가되었습니다.

우선,이 발생하지 않는 것을 당신의 설정했는지 종종 상호 인스턴스화하려는 유형.

둘째, 인터페이스가 제공하는 간접 (추상화) 수준 일반적으로 종속성 주입으로 작업 할 때 충분합니다.

WindowsButton, MacButton, WindowsScrollBar, MacScrollbar 등이있는 WindowsGui 대 MacGui 대 ...의 전형적인 예는 방문자 및 / 또는 인터프리터 패턴을 사용하여 구체적인 버튼, 스크롤바 등을 정의하여 구현하기가 더 쉽습니다 . 실제 행동.


그것에 대한 특정 목적이 있습니다. 의존성 주입을 사용하면 복합 루트에서 서비스 로케이터가 더 아래로 내려가는 것을 원하지 않습니다. 대신 주입 된 추상 팩토리를 사용합니다.
Adam Tuliper-MSFT

2
음 ... DI와 함께 서비스 로케이터를 사용하는 것은 안티 패턴입니다. Abstract Factory는 런타임 값에서 DEPENDENCIES를 생성해야 할 때 보편적 인 솔루션입니다.
TheMentor

1

인스턴스화가 매우 복잡하고 단일 팩토리로는 너무 복잡하고 추하고 UI가 이해하기에는 너무 복잡한 곳에서 단순한 팩토리 패턴보다는 추상 팩토리 패턴이있는 곳이 있다고 생각합니다.

이것이 단일 클래스가 아닌 TYPE_A 브랜드라고 가정 해 봅시다. 100 가지 종류의 유사한 Type-A 클래스가 있고 그로부터 하나의 객체를 인스턴스화해야한다고 가정 해 보겠습니다. 많은 유사한 유형의 객체 브랜드에서 올바른 객체를 만들기 위해 필요한 세부적인 정교한 정보가 있다고 상상해보십시오.이 객체 엔티티에서는 어떤 매개 변수를 조정하고 어떻게 조정해야하는지 정확히 알아야합니다.

이 브랜드를위한 특별한 팩토리에서 우리는 그것들을 차별화하고 인스턴스화 할 정확한 객체와 그것을 인스턴스화하는 방법을 얻을 것입니다. 우리는 인터넷 (온라인 상점에서 어떤 색상을 사용할 수 있는지 가정 해 보겠습니다)의 입력과 백그라운드에서 실행중인 다른 애플리케이션 및 서비스 (UI가 인식하지 못하는 매개 변수)를 통해 알 수 있습니다.

그리고 아마도 내일 우리는 인스턴스화하기 위해 type_B와 type_C의 또 다른 패밀리를 가질 것입니다. 따라서 UI는 사용자가 "type_A", "type_B"또는 "type_C"를 원하는지 여부를 알 수있는 "if else"를 갖습니다. 그러나 팩토리 클래스는 빌드 할 유형 (패밀리에서)의 클래스를 정확하게 결정합니다. 조정 방법 – 매개 변수에 설정하거나 계약자에게 보낼 값. 이 모든 것-UI가 인식하지 못하는 많은 매개 변수에 따라. 이 모든 것은 단일 공장 수업에 너무 많은 것입니다.


1

실제 예제는 DbConnection, DbCommand 및 DbDataAdapter를 포함하는 추상 기본 클래스가 있고 System.Data.SqlClient 및 System.Data.OracleClient와 같은 .NET Framework 데이터 공급자가 공유하는 System.Data.Common 네임 스페이스에서 제공됩니다. 개발자가 특정 데이터 공급자에 의존하지 않는 일반 데이터 액세스 코드를 작성할 수 있습니다.

DbProviderFactories 클래스는 DbProviderFactory 인스턴스를 만들기위한 정적 메서드를 제공합니다. 그런 다음 인스턴스는 런타임에 제공된 연결 문자열과 공급자 정보를 기반으로 올바른 강력한 형식의 개체를 반환합니다.

예:

 DataTable allProvidersTable = DbProviderFactories.GetFactoryClasses();

여기에 이미지 설명 입력

        /* Getting SqlClient family members */
        DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");
        DbCommand dbCommand = dbProviderFactory.CreateCommand();
        DbConnection dbConnection = dbProviderFactory.CreateConnection();
        DbDataAdapter dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        SqlClientFactory sqlClientFactory = (SqlClientFactory)dbProviderFactory;
        SqlConnection sqlConnection = (SqlConnection)dbConnection;
        SqlCommand sqlCommand = (SqlCommand) dbCommand;
        SqlDataAdapter sqlDataAdapter = (SqlDataAdapter) dbDataAdapter;

        /* Getting OracleClient family members*/
        dbProviderFactory = DbProviderFactories.GetFactory("System.Data.OracleClient");
        dbCommand = dbProviderFactory.CreateCommand();
        dbConnection = dbProviderFactory.CreateConnection();
        dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        OracleClientFactory oracleClientFactory = (OracleClientFactory)dbProviderFactory;
        OracleConnection oracleConnection = (OracleConnection)dbConnection;
        OracleCommand oracleCommand = (OracleCommand)dbCommand;
        OracleDataAdapter oracleDataAdapter = (OracleDataAdapter)dbDataAdapter;

예 -2 여기에 이미지 설명 입력

코드 솔루션 아키텍처 여기에 이미지 설명 입력

구체적인 Factory 인스턴스는 아래와 같이 static Factory 방식으로 제공됩니다.

public  class FurnitureProviderFactory
{
    public static IFurnitureFactory GetFactory(string furnitureType)
    {
        if (furnitureType == "Wood")
        {
            return new WoodenFurnitureFactory();
        }
        if (furnitureType == "Plastic")
        {
            return new PlasticFurnitureFactory();
        }
        throw new Exception("Undefined Furniture");
    }
}

0

질문에 직접 답하기 위해 이러한 디자인 패턴을 사용하지 않고도 벗어날 수 있습니다.

그러나 현실 세계의 대부분의 프로젝트는 진화하고 있으며 프로젝트의 미래를 보장하기 위해 일종의 확장 성을 제공하고자합니다.

내 경험으로 볼 때 대부분의 경우 Factory가 구현되고 프로젝트가 성장함에 따라 Abstract Factory와 같은 더 복잡한 디자인 패턴으로 변경됩니다.


0

의존성에 관한 것입니다. 긴밀한 결합과 종속성에 관심이 없다면 추상 팩토리가 필요하지 않습니다. 그러나 유지 관리가 필요한 응용 프로그램을 작성하자마자 중요합니다.


0

a.jar을 만들고 다른 사람이 jar를 사용하고 코드에서 새로운 구체적인 객체를 사용하려고한다고 가정 해 보겠습니다. 추상 팩토리를 사용하지 않는 경우 코드를 수정하거나 코드를 덮어 써야합니다. 그러나 추상 팩토리를 사용하는 경우 팩토리를 제공하고 코드에 전달할 수 있으며 모든 것이 정상입니다.

개선 된 버전 : 다음 시나리오를 고려하십시오. 다른 사람이 프레임 워크를 작성했습니다. 프레임 워크는 추상 팩토리와 일부 구체적인 팩토리를 사용하여 런타임에 많은 개체를 만듭니다. 따라서 자신의 팩토리를 기존 프레임 워크에 쉽게 등록하고 자신 만의 개체를 만들 수 있습니다. 프레임 워크는 수정이 불가능하며 추상적 인 팩토리 패턴으로 인해 확장하기 쉽습니다.


0

이 패턴은 클라이언트가 생성 할 유형을 정확히 알지 못하는 경우 특히 유용합니다. 예를 들어 휴대폰만을 판매하는 쇼룸이 삼성에서 만든 스마트 폰에 대한 쿼리를받는다고 가정 해 보겠습니다. 여기서 우리는 생성 될 개체의 정확한 유형을 알지 못합니다 (전화에 대한 모든 정보가 구체적인 개체 형태로 래핑되었다고 가정). 그러나 우리는 삼성에서 제조 한 스마트 폰을 찾고 있다는 것을 알고 있습니다. 이 정보는 우리의 디자인에 Abstract Factory 구현이있는 경우 실제로 활용할 수 있습니다.

C #에서 추상 팩토리 패턴 이해 및 구현

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.