[Python] Factory Design Pattern

미남잉·6일 전
0

Advanced Python

목록 보기
7/10

Factory Design Pattern

객체지향 설계를 하다 보면, 인스턴스를 직접 생성하지 않고 필요한 객체를 상황에 맞게 생성해주는 패턴이 자주 등장한다. 오늘은 그중 대표적인 디자인 패턴인 Factory Pattern에 대해 예제 코드와 함께 정리할 예정이다.

Factory Pattern은 객체 생성 로직을 별도의 클래스나 메서드로 분리하여, 유연하고 확장 가능한 구조를 만드는 디자인 패턴이다.

즉, 직접 클래스를 생성하지 않고, 팩토리 메서드를 통해 객체를 생성한다. 이로 인해 코드를 바꾸지 않고도 새로운 클래스를 쉽게 추가하거나 교체할 수 있게 된다.

객체 생성의 책임을 별도의 팩토리(Factory) 클래스로 위임한다고 이해할 수 있는데, 이는 객체 생성 방식을 캡슐화(숨김)하고, 필요한 객체를 상황에 맞게 유연하게 생성할 수 있도록 해준다.

1. 인터페이스 역할을 하는 추상 클래스 정의

from abc import ABCMeta, abstractstaticmethod

class IPerson(metaclass=ABCMeta):
    @abstractstaticmethod
    def person_method():
        """ Interface Method """
  • IPerson은 추상 클래스이며, person_method()는 반드시 구현해야 한다.

2. 구체 클래스 정의 (Student Teacher)

class Student(IPerson):
    def __init__(self):
        self.name = "Basic Student Name"
    def person_method(self):
        print("I am a student")

class Teacher(IPerson):
    def __init__(self):
        self.name = "Basic Teacher Name"
    def person_method(self):
        print("I am a teacher")
  • IPerson을 상속받고 person_method()를 구현해야만 인스턴스 생성이 가능하다.

3. Factory 클래스 정의

class PersonFactory:
    @staticmethod
    def build_person(person_type):
        if person_type == "Student":
            return Student()
        if person_type == "Teacher":
            return Teacher()
        print("Invalid Type")
        return -1
  • 입력에 따라 적절한 클래스를 생성해 반환한다.
  • 클라이언트 코드에서는 StudentTeacher를 직접 모르더라도 build_person()만 사용하면 됨

4. 실행 로직

if __name__ == "__main__":
    choice = input("What type of person do you want to create?\n")
    person = PersonFactory.build_person(choice)
    if person != -1:
        person.person_method()
  • 사용자의 입력에 따라 동적으로 객체를 생성하고, 해당 객체의 메서드를 실행한다.

코드 실행 예시

What type of person do you want to create?
Student
I am a student

What type of person do you want to create?
Teacher
I am a teacher

What type of person do you want to create?
Alien
Invalid Type

5. @abstractmethod

@abstractmethod는 Python에서 인터페이스(Interface) 또는 템플릿 역할을 하고자 할 때 핵심적으로 사용되는 기능이다.

객체지향 프로그래밍에서 추상 클래스(abstract class) 는 일부 메서드만 정의된 상태로, 자식 클래스가 반드시 오버라이딩해서 구현해야 할 메서드를 강제하고 싶을 때 사용된다.

즉, 자식 클래스가 반드시 구현해야 하는 메서드를 정의하는 데 사용하는 데코레이터이다.

  • 추상 메서드를 포함하는 클래스는 추상 클래스가 됨
  • 해당 클래스는 직접 인스턴스화할 수 없음
  • 상속받는 자식 클래스가 추상 메서드를 모두 구현하지 않으면, 역시 인스턴스화가 불가능함.
from abc import ABC, abstractmethod

class Animal(ABC):  # ABC를 상속받아야 추상 클래스가 됨
    @abstractmethod
    def speak(self):
        pass
  • Animal 클래스는 speak() 메서드를 구현하지 않았기 때문에 추상 클래스이다
  • 이 클래스를 직접 인스턴스화하려고 하면 에러가 발생한다.
class Dog(Animal):
    def speak(self):
        print("Woof!")

class Cat(Animal):
    def speak(self):
        print("Meow")

dog = Dog()
dog.speak()  # Woof!

이때 발생하는 에러는 TypeError: Can't instantiate abstract class Dog with abstract methods speak

추상 메서드를 정적 메서드로 만들 수 있음

from abc import ABCMeta, abstractstaticmethod

class Factory(metaclass=ABCMeta):
    @abstractstaticmethod
    def create():
        pass
  • 추상 클래스를 ABC 또는 ABCMeta 없이 선언하면 작동하지 않음
  • 추상 메서드가 있는 클래스를 인스턴스화하면 런타임 에러 발생함

@abstractmethod는 자식 클래스가 꼭 구현해야 할 메서드를 강제함으로써 코드 구조의 일관성과 안정성을 높여주는 도구이다.

6. 정리

  • 객체 생성 로직을 감추고 싶을 때 -> 의존성을 줄이고 구조를 유연하게 만듦
  • 확장 가능한 구조가 필요할 때 -> 새로운 클래스가 추가되더라도 Factory만 수정
  • 인터페이스 기반으로 동작할 때 -> 추상 클래스를 기반으로 구현 강제 가능
  • @abstractmethod: 자식 클래스에서 반드시 구현해야 하는 메서드 정의
  • ABC / ABCMeta: 추상 클래스를 정의할 때 사용하는 베이스
  • 인스턴스화 제한: 추상 메서드가 남아있는 클래스는 인스턴스 생성 불가
  • 활용 예: 인터페이스 설계, 템플릿 메서드 패턴 등

Factory Pattern은 "어떤 객체를 만들지 결정하는 책임"을 객체 외부로 분리하는 디자인 패턴으로 유지보수성과 확장성이 매우 뛰어나다.

profile
Computer Vision Engineer

0개의 댓글

관련 채용 정보