✅ Abstract Factory (추상 팩토리) 패턴
🎯 의도 (Intent)
- 관련성 있는 객체들의 집합(패밀리)을 생성하기 위한 인터페이스를 제공하며,
구체적인 클래스는 지정하지 않고 객체들을 생성할 수 있도록 하는 패턴입니다.
- 서로 관련된 객체들이 일관성 있게 사용되도록 보장하면서,
클라이언트 코드가 구체 클래스에 의존하지 않도록(느슨한 결합) 합니다.
- 팩토리 메서드(Factory Method)보다 더 큰 수준의 객체 생성(제품군 관리)을 지원합니다.
👉 즉, 제품군의 생성 로직을 캡슐화하여,
구체적인 클래스 없이도 서로 호환되는 객체들을 일관성 있게 생성할 수 있게 합니다.
🧩 구성 요소 (Participants)
-
AbstractFactory (추상 팩토리 인터페이스)
- 관련된 객체(제품군)를 생성하기 위한 추상 메서드 집합을 정의합니다.
- 예:
createButton(), createCheckbox().
-
ConcreteFactory (구체 팩토리 클래스)
AbstractFactory를 구현하여,
특정 제품군의 구체 객체들을 생성합니다.
- 예:
WindowsFactory, MacFactory.
-
AbstractProduct (추상 제품 인터페이스)
- 각 제품이 가져야 할 공통 인터페이스를 정의합니다.
- 예:
Button, Checkbox 인터페이스.
-
ConcreteProduct (구체 제품 클래스)
AbstractProduct를 구현하여
특정 팩토리에서 생성되는 실제 제품을 정의합니다.
- 예:
WindowsButton, MacButton.
-
Client (클라이언트)
AbstractFactory 인터페이스를 사용하여 객체를 생성합니다.
- 구체 클래스에 직접 의존하지 않고, 팩토리를 통해 객체 생성 및 사용을 수행합니다.
📌 작동 방식
- Client는
AbstractFactory 인터페이스를 통해 객체 생성 요청을 합니다.
- ConcreteFactory가 요청받은 제품군의 구체 객체를 생성합니다.
- Client는 생성된 객체를 사용하지만, 구체 클래스는 알 필요가 없습니다.
- 제품군을 바꾸려면 팩토리 객체만 교체하면 됩니다.
✅ Builder (빌더) 패턴
🎯 의도 (Intent)
- 복잡한 객체의 생성 과정을 단계별로 캡슐화하여,
동일한 생성 절차로도 서로 다른 표현(구성)의 객체를 만들 수 있도록 하는 패턴입니다.
- 객체 생성 로직과 표현 방식을 분리하여,
유연하고 가독성 높은 객체 생성을 지원합니다.
- 특히 생성자의 인자가 많거나, 단계별 초기화가 필요한 경우 유용합니다.
👉 즉, 객체 생성 과정을 세분화하여
클라이언트가 객체를 단계적으로 조립할 수 있게 합니다.
🧩 구성 요소 (Participants)
-
Builder (빌더 인터페이스)
- 복잡한 객체를 생성하기 위한 단계별 메서드를 정의합니다.
- 예:
setPartA(), setPartB(), build().
-
ConcreteBuilder (구체 빌더)
Builder 인터페이스를 구현하여
각 단계별로 객체의 부분을 조립합니다.
- 최종적으로 완성된 객체를 반환하는 메서드를 제공합니다.
-
Product (제품 클래스)
- 빌더가 생성하는 복잡한 객체입니다.
- 여러 부품(Part)으로 구성되며, 단계적으로 조립됩니다.
-
Director (감독자)
Builder를 사용하여 객체 생성의 순서(절차)를 정의합니다.
- Builder의 메서드 호출 순서를 관리하지만, 구체적인 구현에는 관여하지 않습니다.
-
Client (클라이언트)
Director와 ConcreteBuilder를 사용하여 최종 객체를 생성합니다.
- 어떤 Builder를 사용할지 선택함으로써 결과 객체를 다양하게 구성할 수 있습니다.
📌 작동 방식
- Client가 사용할
ConcreteBuilder를 선택하고 Director에 전달합니다.
Director는 미리 정의된 절차에 따라 Builder의 메서드를 순차적으로 호출하여 객체를 조립합니다.
ConcreteBuilder는 객체의 각 부분을 생성 및 조립하고, 완성된 Product를 반환합니다.
- 빌더만 교체하면, 동일한 절차로도 다른 표현의 객체를 만들 수 있습니다.
✅ Factory Method (팩토리 메서드) 패턴
🎯 의도 (Intent)
- 객체 생성을 서브클래스에 위임하여,
클라이언트 코드가 구체 클래스(Concrete Class)에 의존하지 않도록 하는 패턴입니다.
- 객체 생성 로직을 별도의 메서드(
factoryMethod)로 분리하여,
확장 시 새로운 제품을 쉽게 추가할 수 있습니다.
- Abstract Factory와 달리, Factory Method는 하나의 제품(Product)을 생성하는 데 집중합니다.
👉 즉, 객체 생성을 캡슐화하여
상위 클래스는 생성의 인터페이스만 정의하고,
구체 클래스에서 실제 인스턴스를 결정하도록 합니다.
🧩 구성 요소 (Participants)
-
Product (제품 인터페이스)
- 생성될 객체들이 따라야 할 공통 인터페이스를 정의합니다.
- 예:
Button 인터페이스.
-
ConcreteProduct (구체 제품 클래스)
Product 인터페이스를 구현하여 실제 생성될 객체를 정의합니다.
- 예:
WindowsButton, MacButton.
-
Creator (창조자, 추상 클래스)
factoryMethod()라는 추상 메서드를 선언하여
제품 객체 생성을 서브클래스에 위임합니다.
- 또한,
Product 객체를 사용하는 일반 메서드(템플릿 역할)를 포함할 수 있습니다.
-
ConcreteCreator (구체 창조자)
Creator의 factoryMethod()를 구현하여
어떤 ConcreteProduct를 생성할지 결정합니다.
-
Client (클라이언트)
Creator를 통해 Product 객체를 사용하지만,
구체적인 생성 로직은 알 필요가 없습니다.
📌 작동 방식
- Client는
Creator의 메서드를 호출하여 제품을 생성합니다.
Creator는 내부적으로 factoryMethod()를 호출하고,
구체적인 제품 생성을 서브클래스(ConcreteCreator)에 위임합니다.
- 새로운 제품군이 필요하면 ConcreteProduct + ConcreteCreator만 추가하면 됩니다.
✅ Prototype (프로토타입) 패턴
🎯 의도 (Intent)
- 새로운 객체를 생성할 때,
클래스를 명시적으로 지정하지 않고 기존 객체를 복제(Clone)하여 생성하는 패턴입니다.
- 객체 생성 비용이 큰 경우(복잡한 초기화 과정, DB 연결, 네트워크 설정 등)
기존 객체를 복사하여 새로운 인스턴스를 빠르게 생성할 수 있습니다.
- 런타임에 동적으로 객체를 생성할 수 있으며,
새로운 객체 유형을 추가할 때 클래스 계층 구조를 변경하지 않아도 됩니다.
👉 즉, 기존 객체를 복제(clone)하여 새로운 객체를 만드는 방식으로,
객체 생성의 유연성과 성능을 높이는 패턴입니다.
🧩 구성 요소 (Participants)
-
Prototype (프로토타입 인터페이스)
- 자신을 복제하는 메서드(예:
clone())를 정의합니다.
- 이 메서드를 통해 새로운 객체를 생성할 수 있습니다.
-
ConcretePrototype (구체 프로토타입 클래스)
Prototype 인터페이스를 구현하고,
clone() 메서드에서 자신의 복사본을 생성합니다.
- 얕은 복사(Shallow Copy) 또는 깊은 복사(Deep Copy)를 구현할 수 있습니다.
-
Client (클라이언트)
- 새로운 객체를 만들 때
new 키워드 대신
프로토타입 객체의 clone() 메서드를 호출하여 복제본을 생성합니다.
- 복제할 객체의 구체적인 클래스는 몰라도 됩니다.
📌 작동 방식
- Client는 사용할 원형 객체(Prototype 인스턴스)를 미리 등록하거나 보관합니다.
- 새로운 객체가 필요할 때
clone()을 호출하여 원형 객체를 복제합니다.
- 복제된 객체는 원본과 같은 상태를 가지며, 필요 시 일부 속성을 수정할 수 있습니다.
- 새로운 타입의 객체를 추가할 때,
Prototype 인터페이스를 구현한 클래스를 추가하기만 하면 됩니다.
✅ Singleton (싱글톤) 패턴
🎯 의도 (Intent)
- 애플리케이션에서 오직 하나의 인스턴스만 존재하도록 보장하고,
그 인스턴스에 전역적으로 접근할 수 있는 방법을 제공하는 패턴입니다.
- 시스템 전체에서 공유되는 리소스(예: 설정, 로그 기록, DB 연결 등)를 관리할 때 사용됩니다.
- 인스턴스가 하나만 생성되도록 제어하므로 메모리 절약과 일관성 유지가 가능합니다.
👉 즉, 특정 클래스의 인스턴스가 단 하나만 존재하도록 보장하고,
어디서든 접근할 수 있는 전역적 접근점을 제공합니다.
🧩 구성 요소 (Participants)
-
Singleton (싱글톤 클래스)
- 자신의 유일한 인스턴스를 정적(Static) 필드로 보관합니다.
- 외부에서 인스턴스를 생성하지 못하도록 생성자를 private으로 제한합니다.
- 인스턴스에 접근하기 위해 *정적 메서드(
getInstance())를 제공합니다.
-
Client (클라이언트)
Singleton.getInstance()를 호출하여 유일한 인스턴스에 접근하고 사용합니다.
- 여러 번 호출하더라도 항상 같은 인스턴스를 반환받습니다.
📌 작동 방식
- 최초 호출 시,
getInstance()가 새로운 인스턴스를 생성하고 정적 필드에 저장합니다.
- 이후 호출 시, 기존에 생성된 인스턴스를 그대로 반환합니다.
- 인스턴스는 전역적으로 공유되며, 항상 동일한 객체를 참조합니다.