추상 팩토리 패턴(Abstract Factory Pattern)은 객체 생성 패턴 중 하나로, 관련된 객체 군을 생성하는 인터페이스를 제공하는 패턴입니다. 이 패턴은 구체적인 클래스에 의존하지 않고, 인터페이스를 통해 객체를 생성함으로써 코드의 유연성과 확장성을 높입니다.

주요 특징
1. 객체 군 생성: 추상 팩토리 패턴은 관련된 객체를 함께 생성할 수 있도록 해줍니다. 예를 들어, 특정 스타일의 UI 컴포넌트를 생성하는 팩토리를 만들 수 있습니다.
2. 인터페이스 제공: 클라이언트는 구체적인 클래스에 의존하지 않고, 인터페이스를 통해 객체를 요청합니다. 이를 통해 코드의 결합도를 낮출 수 있습니다.
3. 확장성: 새로운 제품군을 추가할 때 기존 코드를 변경하지 않고 새로운 팩토리 클래스를 추가하는 방식으로 확장이 가능합니다.
구성 요소
1. 추상 팩토리(Abstract Factory): 객체 생성 메서드의 인터페이스를 정의합니다.
2. 구체 팩토리(Concrete Factory): 추상 팩토리 인터페이스를 구현하여 구체적인 제품 객체를 생성합니다.
3. 추상 제품(Abstract Product): 생성될 객체의 인터페이스를 정의합니다.
4. 구체 제품(Concrete Product): 추상 제품 인터페이스를 구현하는 구체적인 객체입니다.
예시코드
#include <iostream>
// 추상 제품 인터페이스
class Button {
public:
virtual void paint() = 0; // 순수 가상 함수
};
class Checkbox {
public:
virtual void paint() = 0; // 순수 가상 함수
};
// 구체 제품 클래스
class WindowsButton : public Button {
public:
void paint() override {
std::cout << "Windows Button" << std::endl;
}
};
class WindowsCheckbox : public Checkbox {
public:
void paint() override {
std::cout << "Windows Checkbox" << std::endl;
}
};
// 또 다른 구체 제품 클래스
class MacOSButton : public Button {
public:
void paint() override {
std::cout << "MacOS Button" << std::endl;
}
};
class MacOSCheckbox : public Checkbox {
public:
void paint() override {
std::cout << "MacOS Checkbox" << std::endl;
}
};
// 추상 팩토리 인터페이스
class GUIFactory {
public:
virtual Button* createButton() = 0; // 순수 가상 함수
virtual Checkbox* createCheckbox() = 0; // 순수 가상 함수
};
// 구체 팩토리 클래스
class WindowsFactory : public GUIFactory {
public:
Button* createButton() override {
return new WindowsButton();
}
Checkbox* createCheckbox() override {
return new WindowsCheckbox();
}
};
class MacOSFactory : public GUIFactory {
public:
Button* createButton() override {
return new MacOSButton();
}
Checkbox* createCheckbox() override {
return new MacOSCheckbox();
}
};
// 클라이언트 코드
class Application {
private:
Button* button;
Checkbox* checkbox;
public:
Application(GUIFactory* factory) {
button = factory->createButton();
checkbox = factory->createCheckbox();
}
void paint() {
button->paint();
checkbox->paint();
}
};
// 메인 함수
int main() {
GUIFactory* factory;
// Windows 환경에서 실행
factory = new WindowsFactory();
Application* app1 = new Application(factory);
app1->paint();
delete app1;
delete factory;
// MacOS 환경에서 실행
factory = new MacOSFactory();
Application* app2 = new Application(factory);
app2->paint();
delete app2;
delete factory;
return 0;
}
코드 설명
1. 추상 제품 인터페이스: Button과 Checkbox 클래스를 정의하여 각각의 제품이 가져야 할 메서드를 선언합니다.
2. 구체 제품 클래스: WindowsButton, WindowsCheckbox, MacOSButton, MacOSCheckbox 클래스가 각각의 플랫폼에 맞는 버튼과 체크박스를 구현합니다.
3. 추상 팩토리 인터페이스: GUIFactory 클래스는 버튼과 체크박스를 생성하는 메서드를 선언합니다.
4. 구체 팩토리 클래스: WindowsFactory와 MacOSFactory 클래스는 GUIFactory를 구현하여 각 플랫폼에 맞는 버튼과 체크박스를 생성합니다.
5. 클라이언트 코드: Application 클래스는 팩토리를 통해 버튼과 체크박스를 생성하고, paint() 메서드를 호출하여 생성된 UI 요소를 표시합니다.
6. 메인 함수: main 함수에서 WindowsFactory와 MacOSFactory를 사용하여 각각의 UI 요소를 생성하고, 클라이언트 애플리케이션을 실행합니다.
이와 같이 추상 팩토리 패턴을 사용하면 클라이언트는 구체적인 클래스에 의존하지 않고, 인터페이스를 통해 객체를 생성할 수 있어 코드의 유연성과 확장성이 높아집니다.
실행결과 :
Windows Button
Windows Checkbox
MacOS Button
MacOS Checkbox
실행 과정 설명:
1. Windows 환경에서 실행:
- WindowsFactory 객체가 생성되고, 이를 사용하여 Application 객체가 생성됩니다.
- Application 생성자에서 createButton()과 createCheckbox() 메서드를 호출하여 WindowsButton과 WindowsCheckbox 객체가 생성됩니다.
- app1->paint() 호출 시, WindowsButton과 WindowsCheckbox의 paint() 메서드가 각각 호출되어 "Windows Button"과 "Windows Checkbox" 메시지가 출력됩니다.
2. MacOS 환경에서 실행:
- 이후 MacOSFactory 객체가 생성되고, 새로운 Application 객체가 생성됩니다.
- Application 생성자에서 createButton()과 createCheckbox() 메서드를 호출하여 MacOSButton과 MacOSCheckbox 객체가 생성됩니다.
- app2->paint() 호출 시, MacOSButton과 MacOSCheckbox의 paint() 메서드가 각각 호출되어 "MacOS Button"과 "MacOS Checkbox" 메시지가 출력됩니다.
예시코드 하나 더 보겠습니다.
#include <iostream>
#include <string>
using namespace std;
// Abstract Product A
class Chair {
public:
virtual void sitOn() const = 0; // Pure virtual function
virtual ~Chair() {}
};
// Concrete Product A1
class ModernChair : public Chair {
public:
void sitOn() const override {
cout << "Sitting on a modern chair." << endl;
}
};
// Concrete Product A2
class VictorianChair : public Chair {
public:
void sitOn() const override {
cout << "Sitting on a Victorian-style chair." << endl;
}
};
// Abstract Product B
class Sofa {
public:
virtual void lieOn() const = 0; // Pure virtual function
virtual ~Sofa() {}
};
// Concrete Product B1
class ModernSofa : public Sofa {
public:
void lieOn() const override {
cout << "Lying on a modern sofa." << endl;
}
};
// Concrete Product B2
class VictorianSofa : public Sofa {
public:
void lieOn() const override {
cout << "Lying on a Victorian-style sofa." << endl;
}
};
// Abstract Factory
class FurnitureFactory {
public:
virtual Chair* createChair() const = 0;
virtual Sofa* createSofa() const = 0;
virtual ~FurnitureFactory() {}
};
// Concrete Factory 1
class ModernFurnitureFactory : public FurnitureFactory {
public:
Chair* createChair() const override {
return new ModernChair();
}
Sofa* createSofa() const override {
return new ModernSofa();
}
};
// Concrete Factory 2
class VictorianFurnitureFactory : public FurnitureFactory {
public:
Chair* createChair() const override {
return new VictorianChair();
}
Sofa* createSofa() const override {
return new VictorianSofa();
}
};
// Client code
void clientCode(const FurnitureFactory& factory) {
Chair* chair = factory.createChair();
Sofa* sofa = factory.createSofa();
chair->sitOn();
sofa->lieOn();
delete chair;
delete sofa;
}
int main() {
cout << "Modern furniture factory in use:\n";
ModernFurnitureFactory modernFactory;
clientCode(modernFactory);
cout << "\nVictorian furniture factory in use:\n";
VictorianFurnitureFactory victorianFactory;
clientCode(victorianFactory);
return 0;
}
코드 설명:
- 추상 제품 클래스 (Chair와 Sofa):
- Chair와 Sofa는 추상 제품의 인터페이스를 정의하며, 구체적인 제품들이 이를 구현합니다.
- 구체적인 제품 클래스:
- ModernChair와 VictorianChair: 각각 현대식 의자와 빅토리아 스타일의 의자를 나타냅니다.
- ModernSofa와 VictorianSofa: 각각 현대식 소파와 빅토리아 스타일 소파를 나타냅니다.
- 추상 팩토리 (FurnitureFactory):
- 서로 관련된 제품(의자와 소파)을 생성할 수 있는 인터페이스를 제공합니다.
- createChair와 createSofa라는 두 가지 순수 가상 메서드가 포함되어 있습니다.
- 구체적인 팩토리 클래스:
- ModernFurnitureFactory: 현대식 가구(ModernChair, ModernSofa)를 생성합니다.
- VictorianFurnitureFactory: 빅토리아 스타일 가구(VictorianChair, VictorianSofa)를 생성합니다.
- 클라이언트 코드:
- 클라이언트는 추상 팩토리를 사용하여 제품을 생성합니다. 특정 제품군(Modern 또는 Victorian)에 대한 세부 사항은 팩토리 구현에 캡슐화되어 있습니다.
출력 결과:
프로그램을 실행하면 아래와 같은 출력이 예상됩니다:
Modern furniture factory in use:
Sitting on a modern chair.
Lying on a modern sofa.
Victorian furniture factory in use:
Sitting on a Victorian-style chair.
Lying on a Victorian-style sofa.
추상 팩토리 패턴을 사용하면 코드 유지보수에 여러 가지 장점이 있습니다
1. 결합도 감소: 클라이언트 코드가 구체적인 클래스에 의존하지 않고 인터페이스에만 의존하기 때문에, 특정 구현을 변경하더라도 클라이언트 코드에 영향을 주지 않습니다. 이는 코드의 변경과 유지보수를 용이하게 합니다.
2. 확장성: 새로운 제품군이나 구현을 추가할 때, 기존 코드를 수정할 필요 없이 새로운 구체 팩토리 클래스를 추가하면 됩니다. 이는 새로운 기능을 추가할 때 코드의 안정성을 높입니다.
3. 일관성 유지: 같은 제품군 내에서 일관된 방식으로 객체를 생성할 수 있어, 제품 간의 일관성을 유지하는 데 도움이 됩니다. 이는 코드의 이해도를 높이고, 버그 발생 가능성을 줄입니다.
4. 테스트 용이성: 인터페이스를 통해 객체를 생성하기 때문에, 모의 객체(mock object)를 쉽게 사용할 수 있습니다. 이는 유닛 테스트를 작성할 때 유용하여, 테스트 코드의 유지보수성을 높입니다.
5. 코드 가독성 향상: 추상 팩토리 패턴을 사용하면 각 제품의 생성 로직이 명확히 분리되어 있어, 코드의 가독성이 향상됩니다. 이는 다른 개발자가 코드를 이해하고 수정하는 데 도움을 줍니다.
6. 의존성 관리: 객체 생성 로직을 팩토리 클래스에 집중시킴으로써, 의존성 관리를 더 쉽게 할 수 있습니다. 이는 종속성을 명확히 하고, 코드의 구조를 보다 깔끔하게 유지하는 데 기여합니다.
7. 이러한 장점들은 소프트웨어 개발 과정에서 유지보수성과 확장성을 크게 향상시켜, 장기적으로 코드 품질을 높이는 데 기여합니다.
이러한 장점들은 소프트웨어 개발 과정에서 유지보수성과 확장성을 크게 향상시켜, 장기적으로 코드 품질을 높이는 데 기여합니다.
추상 팩토리 패턴은 여러 관련 객체를 일관되게 생성할 수 있는 유연성과 확장성을 제공하여, 복잡한 시스템에서 일관된 제품군을 관리하는 데 적합합니다. 다른 디자인 패턴들과 비교했을 때, 이러한 장점들은 코드의 유지보수성과 확장성을 높이는 데 크게 기여합니다. 각 패턴의 목적에 따라 적합한 상황이 다르기 때문에, 프로젝트의 요구사항에 따라 적절한 패턴을 선택하는 것이 중요합니다.
'c c++ mfc' 카테고리의 다른 글
디자인패턴 - 팩토리 메소드(Factory Method) (0) | 2025.03.17 |
---|---|
디자인패턴 - 빌더 패턴(Builder Pattern) (0) | 2025.03.17 |
Visual Studio 재배포 패키지가 설치되지 않는 문제 해결방법 (2) | 2024.10.11 |
UML Sequence Diagram에서 Boundary, Control, Entity 클래스가 하는 역할은? (0) | 2024.05.09 |
GFlags 를 이용하여 메모리 누수 찾기 (1) | 2024.01.22 |