본문 바로가기
공부/Object-Oriented Design Pattern

Factory Method Pattern (팩토리 메소드 패턴)

by 혼밥맨 2021. 5. 7.
반응형

Factory Method Pattern (팩토리 메소드 패턴)

 

출처 : www.tutorialspoint.com/design_pattern/factory_pattern.htm

출처 : www.javatpoint.com/factory-method-design-pattern

출처: www.journaldev.com/1392/factory-design-pattern-in-java

출처 : refactoring.guru/design-patterns/factory-method

 

Factory Method

/ Design Patterns / Creational Patterns Factory Method Also known as: Virtual Constructor Intent Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objec

refactoring.guru

 

 

A Factory Pattern or Factory Method Pattern says that just define an interface or abstract class for creating an object but let the subclasses decide which class to instantiate. In other words, subclasses are responsible to create the instance of the class.

 

Factory Pattern(공장 패턴) 또는 Factory Method Pattern(공장 메서드 패턴)은 객체를 생성하기 위한 인터페이스 또는 추상 클래스를 정의하지만 하위 클래스가 인스턴스화할 클래스를 결정하도록 합니다. 즉, 하위 클래스는 클래스의 인스턴스를 만들 책임이 있습니다.

 

Intent

Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.

 

Factory Method는 슈퍼클래스에서 객체를 생성하기 위한 인터페이스를 제공하지만 하위 클래스가 생성될 객체의 유형을 변경할 수 있도록 하는 생성 설계 패턴이다.

Problem

Imagine that you’re creating a logistics management application. The first version of your app can only handle transportation by trucks, so the bulk of your code lives inside the Truck class.

After a while, your app becomes pretty popular. Each day you receive dozens of requests from sea transportation companies to incorporate sea logistics into the app.

처음에는 Truck class만 있었는데, 서비스가 커져서 해운업체에서도 요청을 한다.

 

Great news, right? But how about the code? At present, most of your code is coupled to the Truck class. Adding Ships into the app would require making changes to the entire codebase.

갑자기 Ships 클래스를 만들라고하면 너무 많은 수정이 필요하다.

 

Moreover, if later you decide to add another type of transportation to the app, you will probably need to make all of these changes again.

 

As a result, you will end up with pretty nasty code, riddled with conditionals that switch the app’s behavior depending on the class of transportation objects.

결과적으로, 멋지지 않은 코드로 마무리될 것이다. 

Solution

The Factory Method pattern suggests that you replace direct object construction calls (using the new operator) with calls to a special factory method. Don’t worry: the objects are still created via the new operator, but it’s being called from within the factory method. Objects returned by a factory method are often referred to as products.

 

At first glance, this change may look pointless: we just moved the constructor call from one part of the program to another.

언뜻 보기에는 이러한 변화가 무의미해 보일 수 있습니다. 우리는 단지 프로그램의 한 부분에서 다른 부분으로 생성자 호출을 이동했을 뿐입니다.

 

However, consider this: now you can override the factory method in a subclass and change the class of products being created by the method.

그러나. 이제 하위 클래스의 Factory method을 재정의하고 메서드에서 생성되는 제품 클래스를 변경할 수 있습니다.

 

There’s a slight limitation though: subclasses may return different types of products only if these products have a common base class or interface. Also, the factory method in the base class should have its return type declared as this interface.

그러나 약간의 제한이 있습니다. 하위 클래스는 다른 유형의 제품을 반환할 수 있습니다. 이러한 제품에 common base class 또는 interface가 있는 경우에만 반환할 수 있습니다. 또한 기본 클래스의 factory method은 반환 형식을 이 인터페이스로 선언해야 합니다.

 

For example, both Truck and Ship classes should implement the Transport interface, which declares a method called deliver. Each class implements this method differently: trucks deliver cargo by land, ships deliver cargo by sea.

예를 들어, Truck 과 Ship 클래스는 Transport라는 인터페이스를 implement해야합니다. 각 클래스는 deliver라는 공통 메소드를 가지고 있지만, 다르게 작동해야 합니다. Truck은 cargo를 육지에서, Ships는 cargo를 바다에서 deliver합니다.

 

The factory method in the RoadLogistics class returns truck objects, whereas the factory method in the SeaLogistics class returns ships.

RoadLogistics는 truck 객체를 반환하고, SeaLogistics는 ships 객체를 반환합니다.

 

The code that uses the factory method (often called the client code) doesn’t see a difference between the actual products returned by various subclasses. The client treats all the products as abstract Transport. The client knows that all transport objects are supposed to have the deliver method, but exactly how it works isn’t important to the client.

 

 

Structure

  1. The Product declares the interface, which is common to all objects that can be produced by the creator and its subclasses.
  2. Concrete Products are different implementations of the product interface.
  3. The Creator class declares the factory method that returns new product objects. It’s important that the return type of this method matches the product interface.Note, despite its name, product creation is not the primary responsibility of the creator. Usually, the creator class already has some core business logic related to products. The factory method helps to decouple this logic from the concrete product classes. Here is an analogy: a large software development company can have a training department for programmers. However, the primary function of the company as a whole is still writing code, not producing programmers.
  4. You can declare the factory method as abstract to force all subclasses to implement their own versions of the method. As an alternative, the base factory method can return some default product type.
  5. Concrete Creators override the base factory method so it returns a different type of product.
  6. Note that the factory method doesn’t have to create new instances all the time. It can also return existing objects from a cache, an object pool, or another source.

Applicability

 Use the Factory Method when you don’t know beforehand the exact types and dependencies of the objects your code should work with.

코드가 작동해야 하는 객체의 exact types과 dependencies을 사전에 모르는 경우 factory method을 사용하십시오.

 

 The Factory Method separates product construction code from the code that actually uses the product. Therefore it’s easier to extend the product construction code independently from the rest of the code.

 

For example, to add a new product type to the app, you’ll only need to create a new creator subclass and override the factory method in it.

 

Use the Factory Method when you want to provide users of your library or framework with a way to extend its internal components.

라이브러리 또는 프레임워크의 사용자에게 내부 구성요소 (internal components)를 확장하는 방법을 제공하려면 Factory Method을 사용하십시오.

 

 Inheritance is probably the easiest way to extend the default behavior of a library or framework. But how would the framework recognize that your subclass should be used instead of a standard component?

 

The solution is to reduce the code that constructs components across the framework into a single factory method and let anyone override this method in addition to extending the component itself.

 

Let’s see how that would work. Imagine that you write an app using an open source UI framework. Your app should have round buttons, but the framework only provides square ones. You extend the standard Button class with a glorious RoundButton subclass. But now you need to tell the main UIFramework class to use the new button subclass instead of a default one.

 

To achieve this, you create a subclass UIWithRoundButtons from a base framework class and override its createButton method. While this method returns Button objects in the base class, you make your subclass return RoundButton objects. Now use the UIWithRoundButtons class instead of UIFramework. And that’s about it!

 

FactoryShape Example 예시

Circle.java

1
2
3
4
5
6
7
public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}
cs

 

FactoryPatternDemo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class FactoryPatternDemo {
 
   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();
 
      //get an object of Circle and call its draw method.
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //call draw method of Circle
      shape1.draw();
 
      //get an object of Rectangle and call its draw method.
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //call draw method of Rectangle
      shape2.draw();
 
      //get an object of Square and call its draw method.
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //call draw method of square
      shape3.draw();
   }
}
cs

 

Rectangle.java

1
2
3
4
5
6
7
public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}
cs

 

Shape.java

1
2
3
public interface Shape {
   void draw();
}
cs

 

ShapeFactory.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ShapeFactory {
 
   //use getShape method to get object of type shape
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
 
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
 
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
 
      return null;
   }
}
cs

 

Square.java

1
2
3
4
5
6
7
public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}
cs

 

Result

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.

 

 

다른 예시

www.javatpoint.com/factory-method-design-pattern

반응형

댓글