설계패턴 7. Factory pattern

LSDrug·2024년 6월 9일

설계패턴(完)

목록 보기
7/26

이전까지는 객체 지향의 의미와 객체 지향에서 자주 쓰는 방법적인 측면, 그리고 SOLID Principle에 관해 알아보았다.

이제 본격적으로 코드 설계에 필요한 패턴에 관해 알아보도록 하자.

Creation Design Pattern

Creation Design Pattern은 설계 패턴의 한 종류이다. 이 패턴은 오브젝트를 생성하는 방법을 다루는 패턴으로 객체 생성만을 위한 패턴이라고 할 수 있다.

해당 패턴을 사용하는 이유는 다음과 같다.

  1. 간단하지 않을 때, 일괄적인 생성을 위해서 사용한다.
  2. 쉽게 사용하기 위해서 사용한다.

해당 패턴의 종류는 다음과 같다.

  • Factory Pattern
    -Simple Factory, Factory Method, Abstract Factory
  • Builder Pattern
  • Singleton Pattern
  • Prototype

(Simple) Factory Pattern

  • 객체지향에서 팩토리란 다른 클래스의 객체를 생성하는 클래스를 말한다.
  • 객체의 생성을 별도의 클래스, 즉, 팩토리로 캡슐화하는 것
  • 일반적으로 팩토리는 객체와 관련 메소드로 구성된다.
  • 클라이언트는 특정 인자와 함께 메소드를 호출하고 팩토리는 해당 객체를 생성, 반환 한다. 다만, 특정 인자는 있을 수도 있고 없을 수도 있다.

  • 공장은 함수 또는 클래스로 나타낼 수도 있다.
  • 공장에 원하는 물건을 만들어 달라고 요청 하면 다른 일렬의 과정 없이 그 제품을 만들어 낼 수 있다.

해당 패턴을 함수로 표현한 예시 코드를 보자.

# 제품 정의
class Car:
  def drive(self):
    return "Car driving."

class Truck:
  def drive(self):
    return "Truck driving."

class Motorcycle:
  def drive(self):
    return "Motorcycle zooming."

# 공장
class VehicleFactory:
  def get_vehicle(self, vehicle_type):
    if vehicle_type == 'car':
      return Car()
    elif vehicle_type == 'truck':
      return Truck()
    elif vehicle_type == 'motorcycle':
      return Motorcycle()
    else:
      raise ValueError('Unknown vehicle type')

# 클라이언트 요청
factory = VehicleFactory()

car = factory.get_vehicle('car')
print(car.drive()) # Car driving

truck = factory.get_vehicle('truck')
print(truck.drive()) # Truck driving

motorcycle = factory.get_vehicle('motorcycle')
print(motorcycle.drive()) # Motorcycle zooming

해당 코드는 VehicleFactory 메서드를 이용해 기본적인 골격을 세우고, 각 생성마다 팩토리를 이용해 생성하도록 하였다.

클래스를 이용해 표현하는 방법도 있다.

from enum import Enum

class RobotEnum(Enum):
  CAT = 0
  DOG = 1

class Robot:
  def speak(self):
    pass

class Cat(Robot):
  def speak(self):
    print("meow")

class Dog(Robot):
  def speak(self):
    print("bark")

class RobotFactory:
  def makeRobot(self, robot:RobotEnum):
    if robot == RobotEnum.CAT:
      return Cat()
    elif robot == RobotEnum.DOG:
      return DOG()

fac1 = RobotFactory()
dog = fac1.makeRobot(RobotEnum.DOG)
deg.speak()
cat = fac1.makeRobot(RobotEnum.CAT)
cat.speak()

해당 코드를 UML로 표현할 수 있다. 이를 표현하면 다음과 같다.

해당 그림은 메서드를 이용한 Factory와 클래스로 표현된 Factory 전부를 나타내고 있다. 따라서 RobotEnum에는 x 표시가 있다. 만약 클래스를 이용할 경우에는 반대의 경우를 생각하면 된다.

패턴의 의의

  • 사용자가 오브젝트들의 생성과정을 클라이언트가 직접 다룰 필요가 없게된다.
  • 그러나 어떤 상황에서는 오브젝트를 만드는 과정이 복잡할 수 있다.
  • 오브젝트의 복잡한 생성과정을 팩토리에 숨기고 클라이언트는 "명령" 하면 필요한 오브젝트만 만들어서 리턴해준다는 개념이다.
  • Factory Method pattern, Singleton pattern, Builder pattern 에서 해당 패턴이 응용된다.

Factory Method Pattern

해당 패턴은 인스턴스를 만드는 방법을 상위 클래스 측에서 결정하지만, 구체적인 이름까지는 결정하지 않는 패턴이다.

즉, 구체적인 내용은 모두 하위 클래스 측에서 수행한다.

따라서 인스턴스 생성을 위한 골격과 실제 인스턴스 생성의 클래스를 분리할 수 있다.

사용자가 오브젝트들의 생성과정을 클라이언트가 직접 다룰 필요가 없게 된다.

종합하면 다음으로 정의할 수 있다.

객체 생성을 서브클래스로 위임하여 팩토리 메서드를 가진 부모 클래스를 정의하고, 실제 객체 생성은 이 메서드를 오버라이딩하는 서브클래스에서 이루어지도록 하는 방법을 사용하는 팩토리 패턴

부모 클래스(본진), 서브 클래스(멀티)라고 볼 수 있다.

이전에 사용했던 로봇에 관련된 사진으로 예시를 들자면 다음과 같다.

뼈대 공장을 세우고 그 공장의 여러 지점을 세운 후 객체를 받도록 한다.

해당 패턴은 여러 기능을 팩토리에 추가할 때 사용한다.

Framework의 내용을 수정하지 않아도 전혀 다른 제품과 공장을 만들 수 있다. 즉, 의존하고 있지 않다.

Abstract Factory Pattern

추상 팩토리 패턴관련성이 있는 여러 종류의 객체를 생성하기 위한 인터페이스를 제공하는 생성 디자인 패턴이다.

구체적인 클래스에 대한 정보 없이도 서로 연관되거나 의존적인 객체의 군을 생성할 수 있도록 해 준다.

팩토리 자체를 추상화 시킴으로써 오브젝트들을 쉽게 생성할 수 있다.

장점

  • 추상화 수준에서 일관성: 추상 팩토리 패턴은 객체 생성의 추상화 수준을 높여, 시스템의 나머지 부분과 생성 로직을 분리한다.
  • 확장성: 새로운 종류의 객체를 시스템에 추가하기 위해 기존 코드를 변경할 필요 없이, 새로운 Concrete Factory를 추가함으로써 확장할 수 있다.
  • 교체 용이성 및 유연성: 클라이언트는 실행 시간에 필요에 따라 다른 Concrete Factory를 사용할 수 있으며, 이를 통해 생성되는 객체 군을 쉽게 교체가능하다.

단점

  • 복잡성 증가: 많은 클래스와 인터페이스가 도입됨으로써 시스템의 전반적인 복잡성이 증가할 수 있다. 이는 가독성의 하락으로 이어진다.
  • 확장성의 제한: 추상 팩토리 인터페이스에 새로운 종류의 제품을 추가하는 것은 어렵다. 이는 기존 팩토리 클래스 모두를 변경해야 할 수 있기 때문이다.

해당 코드에 관한 사진 예시는 다음과 같다.


profile
마약같은 코딩, 마약같은 코딩러

0개의 댓글