source

설계 패턴:팩토리 vs 팩토리 방법 vs 추상 팩토리

goodcode 2022. 9. 1. 23:13
반응형

설계 패턴:팩토리 vs 팩토리 방법 vs 추상 팩토리

나는 웹사이트에서 디자인 패턴을 읽고 있었다.

거기서 Factory, Factory method, Abstract factory에 대해 읽었는데 너무 혼란스러워서 정의가 명확하지 않습니다.정의에 따라

공장 - 클라이언트에 인스턴스화 논리를 노출하지 않고 개체를 만들고 공통 인터페이스를 통해 새로 생성된 개체를 참조합니다.공장 출하시 방법을 간략화한 버전입니다.

Factory Method - 객체를 만들기 위한 인터페이스를 정의하지만 인스턴스화할 클래스를 서브클래스가 결정하도록 하고 공통 인터페이스를 통해 새로 생성된 개체를 참조합니다.

추상 팩토리 - 클래스를 명시적으로 지정하지 않고 관련 개체 패밀리를 만들 수 있는 인터페이스를 제공합니다.

Abstract Factory vs Factory Method에 관한 다른 스택오버플로우 스레드도 살펴보았는데, 거기에 그려진 UML 다이어그램은 저의 이해를 더욱 악화시킵니다.

누가 좀 말해줄래?

  1. 이 세 가지 패턴은 어떻게 다른가요?
  2. 언제 사용할까요?
  3. 또한 가능하다면 이러한 패턴과 관련된 Java 예가 있습니까?

세 가지 공장 유형 모두 동일한 작업을 수행합니다.그들은 "스마트 컨스트럭터"입니다.

만약 당신이 두 종류의 과일을 만들 수 있기를 바란다고 가정해 봅시다: 사과와 오렌지.

공장

Factory is "fixed", in that you have just one implementation with no subclassing. In this case, you will have a class like this:
class FruitFactory {

  public Apple makeApple() {
    // Code for creating an Apple here.
  }

  public Orange makeOrange() {
    // Code for creating an orange here.
  }

}

사용 사례:Apple 또는 Orange를 구축하는 것은 컨스트럭터에서 처리하기에는 너무 복잡합니다.

공장에서의 방법

Factory method is generally used when you have some generic processing in a class, but want to vary which kind of fruit you actually use. So:
abstract class FruitPicker {

  protected abstract Fruit makeFruit();

  public void pickFruit() {
    private final Fruit f = makeFruit(); // The fruit we will work on..
    <bla bla bla>
  }
}

의할 수 .그 후, 일반적인 기능을 재이용할 수 있습니다.FruitPicker.pickFruit()서브클래스로 공장 출하 방법을 구현합니다.

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}

추상 공장

Abstract factory is normally used for things like dependency injection/strategy, when you want to be able to create a whole family of objects that need to be of "the same kind", and have some common base classes. Here's a vaguely fruit-related example. The use case here is that we want to make sure that we don't accidentally use an OrangePicker on an Apple. As long as we get our Fruit and Picker from the same factory, they will match.
interface PlantFactory {
  
  Plant makePlant();

  Picker makePicker(); 

}

public class AppleFactory implements PlantFactory {
  Plant makePlant() {
    return new Apple();
  }

  Picker makePicker() {
    return new ApplePicker();
  }
}

public class OrangeFactory implements PlantFactory {
  Plant makePlant() {
    return new Orange();
  }

  Picker makePicker() {
    return new OrangePicker();
  }
}
  1. 이 세 가지 패턴은 어떻게 다른가요?

Factory: 클라이언트에 인스턴스화 로직을 노출하지 않고 개체를 만듭니다.

공장 출하시 방법:개체를 만들기 위한 인터페이스를 정의하되, 인스턴스화할 클래스는 하위 클래스에서 결정하도록 합니다.Factory 메서드를 사용하면 클래스가 하위 클래스로 인스턴스화를 연기할 수 있습니다.

추상 팩토리: 구체적인 클래스를 지정하지 않고 관련 개체 또는 종속 개체의 패밀리를 만들 수 있는 인터페이스를 제공합니다.

AbstractFactory 패턴은 컴포지션을 사용하여 오브젝트 작성의 책임을 다른 클래스에 위임하는 반면 Factory 메서드 설계 패턴은 상속을 사용하여 파생 클래스 또는 하위 클래스에 의존하여 오브젝트를 만듭니다.

  1. 언제 사용할까요?

공장: 클라이언트는 클래스가 필요할 뿐 구체적인 구현은 신경 쓰지 않습니다.

공장 출하시 방법:클라이언트는 런타임에 어떤 구체적인 클래스를 만들어야 하는지 알 수 없지만 작업을 수행할 클래스를 얻으려고 합니다.

공장 출하 시:시스템에서 여러 제품 패밀리를 작성해야 하는 경우 또는 구현 세부사항을 공개하지 않고 제품 라이브러리를 제공해야 하는 경우.

Abstract Factory 클래스는 많은 경우 Factory 메서드를 사용하여 구현됩니다.일반적으로 공장 메서드는 템플릿 메서드에서 호출됩니다.

  1. 또한 가능하다면 이러한 패턴과 관련된 Java 예가 있습니까?

공장 및 공장 방법

목적:

개체를 만들기 위한 인터페이스를 정의하지만 인스턴스화할 클래스는 하위 클래스에서 결정하도록 합니다.Factory Method를 사용하면 클래스가 하위 클래스로 인스턴스화를 연기할 수 있습니다.

UML 다이어그램:

여기에 이미지 설명 입력

제품:Factory 메서드가 작성하는 객체의 인터페이스를 정의합니다.

콘크리트 제품:제품 인터페이스 구현

작성자:출고 시 메서드를 선언합니다.

Concreate Creator:ConcreteProduct 인스턴스를 반환하는 Factory 메서드를 구현합니다.

문제 설명: 게임 인터페이스를 정의하는 Factory Methods를 사용하여 Factory of Games를 만듭니다.

코드 조각:

공장 출하 시의 패턴.공장에서의 방법은 언제 사용합니까?

다른 크레이셔널 패턴과의 비교:

  1. 설계자가 유연성이 필요한 부분을 발견함에 따라 Factory Method를 사용하여 설계 시작(복잡하고 커스터마이즈 가능하며 서브클래스가 급증)하여 Abstract Factory, Prototype 또는 Builder로 진화(더 유연하고 복잡함)

  2. Abstract Factory 클래스는 종종 Factory Methods로 구현되지만 프로토타입을 사용하여 구현할 수도 있습니다.

참고 자료: 설계 패턴의 소스 메이킹

Factory - 복잡한 객체를 작성하기 위한 개별 Factory 클래스.

예: Fruit Factory 클래스를 통해 Fruit 객체를 만듭니다.

class FruitFactory{

public static Fruit getFruit(){...}

}

공장 방법 - 공장용으로 완전히 다른 클래스가 아니라 해당 클래스 자체에 하나의 메서드를 공장으로 추가합니다.

예:

Calendar.getInstance() (Java's Calendar)

추상 팩토리 방법 - 팩토리

예: 컴퓨터 부품 공장을 건설하고 싶다고 합시다.노트북, 데스크톱, 서버 등 여러 종류의 컴퓨터가 있습니다.

각 컴포터 타입에 대해 공장이 필요합니다.그래서 우리는 다음과 같은 고급 공장의 공장을 하나 만듭니다.

ComputerTypeAbstractFactory.getComputerPartFactory(String computerType) ---> This will return PartFactory which can be one of these ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

이제 이 세 개 자체는 다시 공장이 되었다.(Part Factory 자체와 거래하게 됩니다만, 후드에서 추상 공장에서 제공한 내용에 따라 별도의 구현이 이루어집니다.)

  Interface-> PartFactory. getComputerPart(String s), 
Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)

편집: 코멘트의 이의에 따라 Abstract Factory에 정확한 인터페이스를 제공하도록 편집되었습니다.

Vaskaran Sarcar by 제2판 C#Design Patterns에 기재된 다음 이미지를 기반으로 합니다.

1. 심플한 공장 패턴

인스턴스화 로직을 클라이언트에 노출하지 않고 개체를 만듭니다.

SimpleFactory simpleFactory = new SimpleFactory();
IAnimal dog = simpleFactory.CreateDog(); // Create dog
IAnimal tiger = simpleFactory.CreateTiger(); // Create tiger

여기에 이미지 설명 입력

2. 공장에서의 방법 패턴

개체를 만들기 위한 인터페이스를 정의하지만 인스턴스화할 클래스를 하위 클래스가 결정하도록 합니다.

AnimalFactory dogFactory = new DogFactory(); 
IAnimal dog = dogFactory.CreateAnimal(); // Create dog

AnimalFactory tigerFactory = new TigerFactory();
IAnimal tiger = tigerFactory.CreateAnimal(); // Create tiger

여기에 이미지 설명 입력

3. 추상 공장 패턴 (공장 공장)

Abstract Factory는 클래스를 명시적으로 지정하지 않고 관련 객체 패밀리를 만들 수 있는 인터페이스를 제공합니다.

IAnimalFactory petAnimalFactory = FactoryProvider.GetAnimalFactory("pet");
IDog dog = petAnimalFactory.GetDog(); // Create pet dog
ITiger tiger = petAnimalFactory.GetTiger();  // Create pet tiger

IAnimalFactory wildAnimalFactory = FactoryProvider.GetAnimalFactory("wild");
IDog dog = wildAnimalFactory .GetDog(); // Create wild dog
ITiger tiger = wildAnimalFactory .GetTiger();  // Create wild tiger

여기에 이미지 설명 입력

모든 설계 패턴은 작성된 작업 코드가 손상되지 않도록 하기 위해 노력합니다.작업 코드에 손을 대면 기존 작업 흐름에 결함이 있다는 것은 누구나 알고 있으며, 고장나지 않았는지 확인하기 위해 더 많은 테스트를 수행해야 합니다.

공장 패턴은 입력 기준에 따라 객체를 생성하므로 다음과 같은 코드를 쓸 필요가 없습니다.

 if (this) {
     create this kind of object 
 } else { 
     that kind of object 
 }

이것의 좋은 예는 여행 웹사이트이다.여행 웹사이트는 여행(비행기, 기차, 버스) 또는/만 제공하고 호텔 또는/ 관광지 패키지를 제공할 수 있습니다.이제 사용자가 다음을 선택할 때 웹 사이트는 작성해야 하는 개체를 결정해야 합니다.여행이나 호텔 물건만 만들어도 될까요?

포트폴리오에 다른 웹 사이트를 추가하는 것을 상정하고 있으며, 예를 들어 택시 검색과 온라인 결제를 하는 카풀 웹 사이트와 같은 코어가 사용되고 있다고 믿는다면, 추상적인 팩토리를 핵심으로 사용할 수 있습니다.이렇게 하면 택시와 카풀 공장을 하나 더 들일 수 있다.

두 공장은 서로 관계가 없기 때문에 다른 공장에 두는 것이 좋습니다.

이제 확실히 됐으면 좋겠다.이 예를 참고하여 웹 사이트를 다시 한 번 살펴보십시오. 도움이 되었으면 합니다.그리고 제가 패턴을 올바르게 표현했기를 바랍니다:)

이 답변은 '4인방'이라는 책을 참고합니다.

이 책에는 '공장'이나 '단순 공장'이나 '가상 공장'의 정의는 없습니다.통상, 「공장」패턴에 대해 이야기할 때는, 클래스의 특정의 오브젝트를 작성하는 것에 대해 이야기하고 있을 가능성이 있습니다(「빌더」패턴이 아니고, 「공장」패턴이나 「추상 공장」패턴을 참조할 도 있고, 참조하지 않을 도 있습니다.「공장」은 정식 용어가 아니기 때문에, 누구나 실장할 수 있습니다(일부의 사람들, 기업, 커뮤니티는 독자적인 어휘를 가질 수 있습니다).

에는 "Abstract Factory" 및 "Factory Method"에 대한 정의만 포함되어 있습니다.

여기 책의 정의와 두 가지 모두 왜 그렇게 혼란스러울 수 있는지에 대한 간단한 설명이 있습니다.코드 예는 생략합니다.다른 답변에서 찾을 수 있기 때문입니다.

Factory Method(GOF): 오브젝트를 작성하기 위한 인터페이스를 정의합니다만, 인스턴스화할 클래스는 서브 클래스가 결정합니다.Factory 메서드를 사용하면 클래스가 하위 클래스로 인스턴스화를 연기할 수 있습니다.

GOF(Abstract Factory): 구체적인 클래스를 지정하지 않고 관련 개체 또는 종속 개체의 패밀리를 만들 수 있는 인터페이스를 제공합니다.

혼란의 원인: 많은 경우 "Factory Method" 패턴에서 사용된 클래스를 "Factory"라고 부를 수 있습니다.이 클래스는 정의상 추상적입니다.그래서 이 클래스를 '추상 공장'이라고 부르기 쉽습니다.그러나 이것은 클래스 이름일 뿐이므로 "Abstract Factory"(클래스 이름!= 패턴 이름) 패턴과 혼동해서는 안 됩니다."Abstract Factory" 패턴은 다릅니다. 추상 클래스를 사용하지 않습니다. 서로 관련이 있거나 특정 방법으로 생성해야 하는 더 큰 개체 또는 개체의 일부를 만들기 위한 인터페이스(반드시 프로그래밍 언어 인터페이스가 아님)를 정의합니다.

AbstractProductA, A1 and A2 both implementing the AbstractProductA
AbstractProductB, B1 and B2 both implementing the AbstractProductB

interface Factory {
    AbstractProductA getProductA(); //Factory Method - generate A1/A2
}

Factory Method를 사용하여 Abstract Product A의 A1 또는 A2를 생성할 수 있습니다.

interface AbstractFactory {
    AbstractProductA getProductA(); //Factory Method
    AbstractProductB getProductB(); //Factory Method
}

단, Abstract Factory는 여러 팩토리 메서드(예: 2팩토리 메서드)를 가지고 있으며, 이러한 팩토리 메서드를 사용하여 객체/관련 객체 세트를 만듭니다.Abstract Factory를 사용하면 Abstract Product A, Abstract Product B의 A1, B1 개체를 만들 수 있습니다.

원작의 '디자인 패턴'을 인용한 사람은 아무도 없습니다. 재사용 가능한 객체 지향 소프트웨어의 요소: "Creational Patterns 토론"(강조 광산) 섹션의 처음 두 단락에서 답을 제공합니다.

시스템이 작성하는 오브젝트 클래스에 따라 시스템을 파라미터화하는 방법에는 두 가지가 있습니다.한 가지 방법은 객체를 만드는 클래스를 서브클래스로 분류하는 것입니다.이것은 공장 출하 시 메서드(107) 패턴을 사용하는 것에 해당합니다.이 접근법의 주요 단점은 제품의 클래스를 변경하기 위해서만 새로운 서브클래스가 필요할 수 있다는 것입니다.이러한 변화는 단계적으로 진행될 수 있습니다.예를 들어 제품 생성자 자체가 공장 방식으로 생성된 경우 생성자 역시 재정의해야 합니다.

시스템을 파라미터화하는 다른 방법은 객체 구성에 더 의존합니다.제품 객체의 클래스를 파악할 수 있는 객체를 정의하고 이를 시스템의 매개 변수로 만듭니다.이는 Abstract Factory(87), Builder(97) 및 프로토타입(117) 패턴의 주요 측면입니다.이 세 가지 모두 제품 객체를 만드는 새로운 "팩토리 객체"를 만드는 것과 관련이 있습니다.Abstract Factory에는 여러 클래스의 개체를 생성하는 팩토리 개체가 있습니다.Builder는 팩토리 오브젝트가 대응하는 복잡한 프로토콜을 사용하여 복잡한 제품을 점진적으로 구축하도록 합니다.프로토타입은 공장 객체에서 프로토타입 객체를 복사하여 제품을 제작합니다.이 경우 공장 객체와 프로토타입은 동일한 객체입니다. 왜냐하면 프로토타입은 제품의 반품을 담당하기 때문입니다.

언급URL : https://stackoverflow.com/questions/13029261/design-patterns-factory-vs-factory-method-vs-abstract-factory

반응형