본문 바로가기

Develop/Design Pattern

[Design Pattern] 단순 팩토리 (Simple Factory) 패턴

728x90

해당 포스팅은 [Design Pattern] 팩토리 (Factory) 패턴 의 하위 문서입니다.



1. 개요

  • 단순 팩토리 디자인 패턴 (Simple Factory Design Pattern) (이하 단순 팩토리)객체의 생성 부분을 공장(Factory) 클래스에 위임(Delegate)하는 패턴이다.

단순 팩토리는 팩토리 디자인 패턴의 가장 단순한 형태로, 팩토리 디자인 패턴 그 자체의 의미를 갖는다.

2. 상황

  • 객체 생성이 복잡하거나 변경되기 쉬울 때
  • 객체 생성 코드가 중복될 때

3. 다이어그램

simple-factory

3.1. 설명

  • Product 객체를 생성하는 코드는 Factory 클래스의 create() 에 구현되어 있다.
  • 이때, 반드시 생성할 객체를 구분할 수 있는 색인(int), 열거형(Enum), 문자열(String) 등의 정보(type)가 수반되어야 한다.
  • 잘못된 정보가 전달되면 에러(IllegalArgumentException)가 발생한다.

4. 구현

public abstract class Product {}

class ProductA extends Product {}
class ProductB extends Product {}
public class Factory {
  public Product create(String type) {
    switch (type) {
      case "A": return new ProductA();
      case "B": return new ProductB();
      default: throw new IllegalArgumentException("Invalid type"); 
    }
  }
}
public class Client {
  public static void main(String[] args) {
    Factory factory = new Factory();
    Product productA = factory.create("A");
    Product productB = factory.create("B");
  }
}

5. 예시

public abstract class Shape {
  protected double x;
  protected double y;

  public abstract double getArea();

  @Override
  public String toString() {
    return String.format("Position: (%.1f, %.1f)\nArea: %.2f", x, y, getArea());
  }
}

class Rectangle extends Shape {
  private double width;
  private double height;

  public Rectangle(double x, double y, double width, double height) {  
    super.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
  }

  public double getArea() { return width * height; }

  @Override
  public String toString() {
    return "\n[Rectangle]\n" 
      + super.toString() 
      + String.format("\nWidth: %.1f, Height: %.1f", width, height);
  }
}

class Circle extends Shape {
  private double radius;

  public Circle(double x, double y, double radius) { 
    this.x = x;
    this.y = y;
    this.radius = radius; 
  }

  public double getArea() { return Math.PI * Math.pow(radius, 2); }

  @Override
  public String toString() {
    return "\n[Circle]\n"
      + super.toString() 
      + String.format("\nRadius: %.1f", radius);
  }
}
public class ShapeFactory {
  public Shape create(String type, double[] params) throws Exception {
    switch (type) {
      case "Rectangle": 
        if (params.length != 4) 
          throw new Exception("Invalid number of parameter");
        return new Rectangle(params[0], params[1], params[2], params[3]);
      case "Circle": 
        if (params.length != 3)
          throw new Exception("Invalid number of parameter");
        return new Circle(params[0], params[1], params[2]);
      default: throw new IllegalArgumentException("Invalid type");
    }
  }
}
public class Client {
  public static void main(String[] args) throws Exception {
    ShapeFactory factory = new ShapeFactory();
    Shape rectangle = factory.create(
      "Rectangle", 
      new double[] { 50.0, 40.0, 20.0, 30.0 }
    );
    Shape circle = factory.create(
      "Circle", 
      new double[] { 30.0, 20.0, 10.0 }
    );

    System.out.println(rectangle);
    System.out.println(circle);
  }
}

실행결과

[Rectangle]
Position: (50.0, 40.0)
Area: 600.00
Width: 20.0, Height 30.0

[Circle]
Position: (30.0, 20.0)
Area: 314.16
Radius: 10.0

6. 장단점

6.1. 장점

  • 코드 중복 최소화
  • 유연성, 확장성 증가
  • Client 코드 간소화

6.2. 단점

  • SRP 위배 (새로운 객체를 추가 시 수정 필요)

관련 포스팅

728x90