본문 바로가기
컴퓨터과학/디자인패턴

[디자인패턴] 팩토리 패턴 (Factory Pattern)

by 윤호 2021. 10. 18.

목적

객체 생성용 인터페이스 정의

구체적인 클래스를 명시하지 않고 관련되거나 의존적인 객체들을 생성할 수 있는 인터페이스 제공

new는 인터페이스가 아니라 실제 클래스(concrete class)의 객체를 생성

  • OCP에 어긋남 (변경에 대해서 닫혀있지 않다)
    • 생성할 객체가 늘어나면 코드 수정 필요

요소

문제: 실제로 구현되는 클래스의 객체를 생성할 때 객체의 종류가 달라지면 클라이언트 코드를 많이 수정해야함

해결: 생성을 분리해서 캡슐화 시킴

결과: 사용할 객체가 많거나 객체를 생성하는 방법이 변경 되어도 연쇄적인 수정이 적어짐

정의

Creator가 Factory에 해당한다.

ConcreteCreateor는 Product타입의 ConcreteProduct들을 가져와 factoryMethod로 작업한다.

삼각형과 사각형을 생성하는 팩토리 메소드

삼각형이나 사각형을 추가하면 해당 클래스를 추가하고 해당하는 Factory 클래스만 수정하면 됨.

// Main 함수 일부
...
  ShapeFactory sf = new RectangularShapeFactory();
  ArrayList<Shape> shapeList = new ArrayList<Shape>();

  shapeList.add(sf.create("Rectangle", RECTANGLE_POINTS));
  shapeList.add(sf.create("Trapezoid", TRAPEZOID_POINTS));
  shapeList.add(sf.create("Parallelogram", PARALLELOGRAM_POINTS));

  sf = new TriangularShapeFactory();
  shapeList.add(sf.create("Triangle", TRIANGLE_POINTS));
  shapeList.add(sf.create("RightTriangle", RIGHT_TRIANGLE_POINTS));

  for (Shape s : shapeList) {
  System.out.println(s);
  }
...

shapeFacotry를 갈아 끼울 수 있고, 해당 factory에 맞는 shape을 생성할 수 있다.

 

// ShapeFactory 인터페이스
public interface ShapeFactory {

    public Shape create(String type, Point[] points);
}

 

// concrete ShapeFactory
public class RectangularShapeFactory implements ShapeFactory {

    @Override
    public Shape create(String type, Point[] points) {
        if (type.equals("Rectangle")) {
            return new Rectangle(type, points);
        } else if (type.equals("Parallelogram")) {
            return new Parallelogram(type, points);
        } else if (type.equals("Trapezoid")) {
            return new Trapezoid(type, points);
        }
        return null;
    }
}

 

// Shape 추상클래스
public abstract class Shape {
    ...
    public abstract double calcArea();

    @Override
    public String toString() {
    	// calcArea를 사용함 (구현체에서 override하여 알맞은 calc를 수행)
    }
}

 

// Concrete Shape
public class Rectangle extends Shape {

    public Rectangle(String type, Point[] points) {
        super(type, points);
    }

    @Override
    public double calcArea() {
        double width = Math.abs(points[0].getX()-points[1].getX());
        double height = Math.abs(points[0].getY()-points[1].getY());
        return width*height;
    }
}

댓글