logo

팩토리 메소드 디자인 패턴

팩토리 메소드 디자인 패턴은 창조적인 디자인 패턴 이는 슈퍼클래스에서 객체를 생성하기 위한 인터페이스를 제공하여 서브클래스가 생성될 객체의 유형을 변경할 수 있도록 합니다. 객체 생성 로직을 별도의 방법으로 캡슐화하여 생성자와 생성된 객체 간의 느슨한 결합을 촉진합니다. 이 패턴은 생성할 객체의 정확한 유형이 다양하거나 런타임에 결정되어야 할 때 특히 유용하며 객체 생성 시 유연성과 확장성을 제공합니다.

내용의 테이블



팩토리 메소드 디자인 패턴이란 무엇입니까?

팩토리 메소드 디자인 패턴(Factory Method Design Pattern)은 슈퍼클래스에서 객체를 생성하기 위한 인터페이스를 제공하는 동시에 서브클래스가 생성될 객체의 유형을 변경할 수 있도록 허용하기 위해 소프트웨어 엔지니어링에서 사용되는 생성 설계 패턴입니다. 이는 객체 생성 로직을 별도의 방법으로 캡슐화하여 인스턴스화 프로세스를 추상화하고 생성자와 생성된 객체 간의 느슨한 결합을 촉진합니다. 이 패턴을 사용하면 하위 클래스가 특정 유형의 개체를 생성하기 위한 팩토리 메서드의 자체 구현을 정의할 수 있으므로 코드베이스의 유연성, 확장성 및 유지 관리가 가능해집니다.

안키타 로칸데 나이

팩토리 메소드 디자인 패턴은 언제 사용하나요?

팩토리 메소드 디자인 패턴 사용:

  • 객체 생성을 캡슐화하려는 경우: 객체 생성 프로세스가 복잡하거나 프로세스가 조건에 따라 달라질 수 있는 경우 이 논리를 팩토리 메서드에 캡슐화하면 클라이언트 코드를 단순화하고 재사용성을 높일 수 있습니다.
  • 구체적인 클래스에서 클라이언트 코드를 분리하려는 경우: 팩토리 메소드 패턴을 사용하면 인터페이스나 추상 클래스를 통해 객체를 생성하고 클라이언트 코드에서 구체적인 클래스의 특정 구현 세부 정보를 추상화할 수 있습니다. 이는 느슨한 결합을 촉진하고 기존 클라이언트 코드에 영향을 주지 않고 시스템을 더 쉽게 수정하거나 확장할 수 있게 해줍니다.
  • 여러 제품 변형을 지원해야 하는 경우: 애플리케이션이 다양한 제품 변형을 생성해야 하거나 향후 새로운 유형의 제품이 출시될 수 있는 경우, 팩토리 메소드 패턴은 각 제품 유형에 대한 팩토리 메소드를 정의하여 이러한 변형을 수용할 수 있는 유연한 방법을 제공합니다.
  • 사용자 정의 또는 구성을 지원하려는 경우: 팩토리는 구성 로직을 캡슐화하는 데 사용될 수 있으며, 이를 통해 클라이언트는 팩토리 메소드에 매개변수 또는 구성 옵션을 제공하여 생성 프로세스를 사용자 정의할 수 있습니다.

팩토리 메소드 디자인 패턴의 구성요소

1. 창작자

이것은 팩토리 메소드를 선언하는 추상 클래스 또는 인터페이스입니다. 생성자에는 일반적으로 객체 생성을 위한 팩토리 역할을 하는 메서드가 포함되어 있습니다. 또한 생성된 개체와 함께 작동하는 다른 메서드가 포함될 수도 있습니다.

2. 콘크리트 크리에이터

구체적인 Creator 클래스는 특정 유형의 객체를 생성하기 위해 팩토리 메서드를 구현하는 Creator의 하위 클래스입니다. 각 Concrete Creator는 특정 제품을 만드는 일을 담당합니다.

개발자 모드를 비활성화하는 방법

3. 제품

이는 팩토리 메소드가 생성하는 객체에 대한 인터페이스 또는 추상 클래스입니다. 제품은 팩토리 메소드가 생성할 수 있는 모든 객체에 대한 공통 인터페이스를 정의합니다.

4. 콘크리트 제품

구체적인 제품 클래스는 팩토리 메소드가 생성하는 실제 객체입니다. 각 Concrete Product 클래스는 Product 인터페이스를 구현하거나 Product 추상 클래스를 확장합니다.

팩토리 메소드 설계 패턴 예

다음은 팩토리 메소드 디자인 패턴을 이해하기 위한 문제 설명입니다.

2륜차, 3륜차, 4륜차 등 다양한 유형의 차량 생성을 처리해야 하는 소프트웨어 애플리케이션을 생각해 보세요. 각 유형의 차량에는 고유한 속성과 동작이 있습니다.

1. 팩토리 메소드 디자인 패턴 없음

자바
/*package whatever //do not write package name here */ import java.io.*; // Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Client (or user) class class Client {  private Vehicle pVehicle;  public Client(int type) {  if (type == 1) {  pVehicle = new TwoWheeler();  } else if (type == 2) {  pVehicle = new FourWheeler();  } else {  pVehicle = null;  }  }  public void cleanup() {  if (pVehicle != null) {  pVehicle = null;  }  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  Client pClient = new Client(1);  Vehicle pVehicle = pClient.getVehicle();  if (pVehicle != null) {  pVehicle.printVehicle();  }  pClient.cleanup();  } }>
산출
I am two wheeler>

위 디자인의 문제점은 무엇입니까?

위의 코드 디자인에서:

  • 긴밀한 커플링: 클라이언트 클래스Client>구체적인 클래스를 직접 인스턴스화합니다(TwoWheeler>그리고FourWheeler>) 생성 중에 제공된 입력 유형을 기반으로 합니다. 이로 인해 클라이언트와 구체적인 클래스 간의 긴밀한 결합이 발생하여 코드를 유지 관리하고 확장하기가 어려워집니다.
  • 단일 책임 원칙(SRP) 위반: 그만큼Client>클래스는 입력 유형에 따라 인스턴스화할 차량 유형을 결정할 뿐만 아니라 차량 객체의 수명 주기(예: 청소)를 관리하는 역할도 담당합니다. 이는 클래스를 변경할 이유가 하나만 있어야 한다는 단일 책임 원칙을 위반합니다.
  • 제한된 확장성: 새로운 유형의 차량을 추가하려면Client>개방-폐쇄 원칙을 위반하는 클래스입니다. 이 디자인은 기존 코드를 수정하지 않고는 새로운 유형의 차량을 수용할 수 없기 때문에 확장성이 없습니다.

문제를 어떻게 피할 수 있나요?

  • 팩토리 인터페이스 정의: 만들기VehicleFactory>차량을 생성하기 위한 메소드가 포함된 인터페이스 또는 추상 클래스입니다.
  • 콘크리트 팩토리 구현: 구체적인 팩토리 클래스 구현(TwoWheelerFactory>그리고FourWheelerFactory>)는VehicleFactory>특정 유형의 차량 인스턴스를 생성하는 방법을 인터페이스하고 제공합니다.
  • 리팩터링 클라이언트: 수정하다Client>받아들이는 수업VehicleFactory>차량을 직접 인스턴스화하는 대신 인스턴스를 생성합니다. 클라이언트는 공장에 차량을 요청하므로 차량 유형에 따른 조건부 논리가 필요하지 않습니다.
  • 향상된 유연성: 이 접근 방식을 사용하면 새로운 유형의 차량을 추가하는 것이 기존 클라이언트 코드를 수정하지 않고 새 차량 유형에 대한 새 팩토리 클래스를 만드는 것만큼 간단합니다.

2. 팩토리 메소드 디자인 패턴 사용

코드를 구성 요소별 코드로 분류해 보겠습니다.

공장방법디자인패턴

1. 제품 인터페이스

자바
// Product interface representing a vehicle public abstract class Vehicle {  public abstract void printVehicle(); }>

2. 콘크리트 제품

자바
// Concrete product classes representing different types of vehicles public class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } public class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } }>

3. 크리에이터 인터페이스(팩토리 인터페이스)

자바
// Factory interface defining the factory method public interface VehicleFactory {  Vehicle createVehicle(); }>

4. 콘크리트 크리에이터(콘크리트 공장)

자바
// Concrete factory class for TwoWheeler public class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete factory class for FourWheeler public class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } }>

이 예제의 전체 코드:

자바
// Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Factory Interface interface VehicleFactory {  Vehicle createVehicle(); } // Concrete Factory for TwoWheeler class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete Factory for FourWheeler class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } } // Client class class Client {  private Vehicle pVehicle;  public Client(VehicleFactory factory) {  pVehicle = factory.createVehicle();  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  VehicleFactory twoWheelerFactory = new TwoWheelerFactory();  Client twoWheelerClient = new Client(twoWheelerFactory);  Vehicle twoWheeler = twoWheelerClient.getVehicle();  twoWheeler.printVehicle();  VehicleFactory fourWheelerFactory = new FourWheelerFactory();  Client fourWheelerClient = new Client(fourWheelerFactory);  Vehicle fourWheeler = fourWheelerClient.getVehicle();  fourWheeler.printVehicle();  } }>
산출
I am two wheeler I am four wheeler>

위 코드에서:

이런, 자바의 개념
  • Vehicle> 공통 메소드를 정의하는 제품 인터페이스 역할을 합니다. printVehicle()> 모든 콘크리트 제품이 구현해야 하는 사항입니다.
  • TwoWheeler> 그리고 FourWheeler> 다양한 유형의 차량을 대표하는 구체적인 제품 클래스입니다. printVehicle()> 방법.
  • VehicleFactory> 메소드를 사용하여 Creator 인터페이스(Factory Interface) 역할을 합니다. createVehicle()> 팩토리 메소드를 표현합니다.
  • TwoWheelerFactory> 그리고 FourWheelerFactory> 구현하는 구체적인 생성자 클래스(Concrete Factory)입니다. VehicleFactory> 특정 유형의 차량 인스턴스를 생성하는 인터페이스입니다.

팩토리 메소드 디자인 패턴의 사용 사례

다음은 팩토리 메소드 디자인 패턴의 몇 가지 일반적인 응용 프로그램입니다.

  • 창작 프레임워크:
    • JDBC(Java Database Connectivity)는 연결, 명령문 및 결과 세트를 생성하기 위해 팩토리를 광범위하게 사용합니다. Spring 및 Guice와 같은 종속성 주입 프레임워크는 Bean을 생성하고 관리하기 위해 팩토리에 크게 의존합니다.
  • GUI 툴킷:
    • Swing 및 JavaFX는 팩토리를 사용하여 버튼, 텍스트 필드, 레이블과 같은 UI 구성 요소를 생성하므로 UI ​​디자인의 사용자 정의 및 유연성이 가능합니다.
  • 로깅 프레임워크:
    • Log4j 및 Logback과 같은 로깅 프레임워크는 팩토리를 사용하여 다양한 구성으로 로거를 생성하여 로깅 수준 및 출력 대상을 제어할 수 있습니다.
  • 직렬화 및 역직렬화:
    • 객체 직렬화 프레임워크는 종종 팩토리를 사용하여 직렬화된 데이터에서 객체를 생성하고 다양한 직렬화 형식과 버전 관리를 지원합니다.
  • 플러그인 시스템:
    • 플러그인 기반 시스템은 종종 팩토리를 사용하여 플러그인 인스턴스를 동적으로 로드하고 생성하므로 확장성과 사용자 정의가 가능합니다.
  • 게임 개발:
    • 게임 엔진은 종종 팩토리를 사용하여 다양한 유형의 게임 개체, 캐릭터 및 레벨을 생성하여 코드 구성 및 유연성을 향상시킵니다.
  • 웹 개발:
    • 웹 프레임워크는 때때로 팩토리를 사용하여 뷰 구성 요소, 컨트롤러 및 서비스를 생성하여 웹 애플리케이션의 모듈화 및 테스트 가능성을 활성화합니다.

팩토리 메소드 디자인 패턴의 장점

팩토리 메소드 디자인 패턴의 장점은 다음과 같습니다.

올해의 분기
  • 디커플링: 이는 해당 개체를 사용하는 클라이언트 코드에서 개체 생성 논리를 분리합니다. 생성 프로세스를 변경해도 클라이언트 코드를 수정할 필요가 없기 때문에 코드가 더욱 유연하고 유지 관리 가능해집니다.
  • 확장성: 클라이언트 코드를 변경하지 않고도 새로운 제품 유형을 쉽게 도입할 수 있습니다. 새로운 Concrete Creator 서브클래스를 생성하고 팩토리 메소드를 구현하여 새 제품을 생산하기만 하면 됩니다.
  • 테스트 가능성: 테스트 중에 제품 생성을 모의하거나 스텁아웃할 수 있도록 하여 단위 테스트를 단순화합니다. 실제 객체 생성에 의존하지 않고 독립적으로 다양한 제품 구현을 테스트할 수 있습니다.
  • 코드 재사용성: 팩토리 메소드는 객체 생성이 필요한 애플리케이션의 다른 부분에서 재사용될 수 있습니다. 이는 객체 생성 논리를 중앙 집중화하고 재사용하는 것을 촉진합니다.
  • 캡슐화: 클라이언트 코드에서 구체적인 제품 클래스를 숨기므로 특정 구현에 대한 코드 의존도가 낮아집니다. 이는 유지보수성을 향상시키고 결합을 감소시킵니다.

팩토리 메소드 디자인 패턴의 단점

팩토리 메소드 디자인 패턴의 단점은 다음과 같습니다.

  • 복잡성 증가: 추가 클래스와 인터페이스를 도입하여 특히 패턴에 익숙하지 않은 사람들을 위해 코드를 이해하고 유지 관리하기 더 복잡하게 만들 수 있는 추상화 계층을 추가합니다.
  • 간접비: 다형성과 동적 바인딩을 사용하면 성능에 약간의 영향을 줄 수 있지만 대부분의 애플리케이션에서는 무시할 수 있는 경우가 많습니다.
  • 제품 계층 내 긴밀한 결합: 콘크리트 제작자는 여전히 해당 콘크리트 제품과 긴밀하게 연결되어 있습니다. 하나를 변경하면 다른 것도 변경해야 하는 경우가 많습니다.
  • 구체적인 하위 클래스에 대한 종속성: 클라이언트 코드는 여전히 추상 Creator 클래스에 의존하므로 올바른 팩토리 메서드 호출을 수행하려면 구체적인 하위 클래스에 대한 지식이 필요합니다.
  • 남용 가능성: 애플리케이션을 과도하게 엔지니어링하지 않으려면 팩토리 메소드 패턴을 신중하게 사용하는 것이 중요합니다. 간단한 객체 생성은 종종 팩토리 없이 직접 처리될 수 있습니다.
  • 테스트 과제: 팩토리 로직 자체를 테스트하는 것은 더 복잡할 수 있습니다.