추상 팩토리 패턴(Abstract Factory Pattern) 이해하기
추상 팩토리 패턴은 생성 패턴 중 하나로, 서로 관련된 객체 집합을 생성할 수 있는 인터페이스를 제공합니다. 이 패턴을 활용하면 클라이언트가 구체적인 클래스에 의존하지 않고도 객체를 생성할 수 있으며, 다양한 제품군을 일관성 있게 생성할 수 있습니다. 이를 통해 코드의 유지보수성과 확장성을 높일 수 있습니다.
이번 포스트에서는 추상 팩토리 패턴이 무엇인지, 구체적인 구현 방식과 장단점, 그리고 적용 상황을 예제와 함께 알아보겠습니다.
추상 팩토리 패턴이란?
추상 팩토리 패턴은 관련되거나 의존적인 객체들의 집합을 생성하기 위한 인터페이스를 정의합니다. 이 인터페이스는 구체적인 클래스들을 인스턴스화하지 않고도 서로 다른 제품군(Product Family)에 속하는 객체들을 생성할 수 있게 합니다.
추상 팩토리 패턴은 팩토리 메소드 패턴의 확장된 형태로 볼 수 있으며, 다양한 제품을 생성할 수 있는 팩토리 메소드들을 하나의 팩토리에서 통합 관리합니다. 예를 들어, GUI 툴킷에서 윈도우와 버튼을 생성할 때, 테마에 따라 윈도우와 버튼의 스타일이 달라져야 한다면 추상 팩토리 패턴을 통해 이를 관리할 수 있습니다.
추상 팩토리 패턴의 구조
추상 팩토리 패턴은 다음과 같은 요소로 구성됩니다.
- AbstractFactory (추상 팩토리 인터페이스): 생성할 제품들의 팩토리 메소드들을 선언하는 인터페이스입니다.
- ConcreteFactory (구체적인 팩토리): AbstractFactory 인터페이스를 구현하여 각 제품군에 해당하는 객체를 생성합니다.
- AbstractProduct (추상 제품): 생성될 객체의 추상 인터페이스를 정의하며, 제품군의 각 제품에 공통적으로 사용될 메서드를 선언합니다.
- ConcreteProduct (구체적인 제품): AbstractProduct 인터페이스를 구현하는 구체적인 클래스입니다. 각 ConcreteFactory는 ConcreteProduct를 생성하여 특정 제품군에 맞는 객체를 반환합니다.
- Client (클라이언트): AbstractFactory와 AbstractProduct 인터페이스를 사용하여 객체를 생성하며, 구체적인 클래스와는 독립적으로 동작합니다.
예제 코드: GUI 테마 예제
다음은 추상 팩토리 패턴을 사용하여 Windows와 Mac 테마에 따라 서로 다른 스타일의 버튼과 체크박스를 생성하는 예제입니다.
// AbstractProductA
public interface IButton
{
void Render();
}
// AbstractProductB
public interface ICheckbox
{
void Render();
}
// ConcreteProductA1
public class WindowsButton : IButton
{
public void Render() => Console.WriteLine("Rendering Windows-style Button");
}
// ConcreteProductB1
public class WindowsCheckbox : ICheckbox
{
public void Render() => Console.WriteLine("Rendering Windows-style Checkbox");
}
// ConcreteProductA2
public class MacButton : IButton
{
public void Render() => Console.WriteLine("Rendering Mac-style Button");
}
// ConcreteProductB2
public class MacCheckbox : ICheckbox
{
public void Render() => Console.WriteLine("Rendering Mac-style Checkbox");
}
// AbstractFactory
public interface IGUIFactory
{
IButton CreateButton();
ICheckbox CreateCheckbox();
}
// ConcreteFactory1
public class WindowsFactory : IGUIFactory
{
public IButton CreateButton() => new WindowsButton();
public ICheckbox CreateCheckbox() => new WindowsCheckbox();
}
// ConcreteFactory2
public class MacFactory : IGUIFactory
{
public IButton CreateButton() => new MacButton();
public ICheckbox CreateCheckbox() => new MacCheckbox();
}
// Client
public class Application
{
private readonly IButton _button;
private readonly ICheckbox _checkbox;
public Application(IGUIFactory factory)
{
_button = factory.CreateButton();
_checkbox = factory.CreateCheckbox();
}
public void Render()
{
_button.Render();
_checkbox.Render();
}
}
// 사용 예시
class Program
{
static void Main()
{
IGUIFactory factory = new WindowsFactory(); // WindowsFactory 또는 MacFactory로 변경 가능
Application app = new Application(factory);
app.Render();
}
}
위 예제에서 WindowsFactory와 MacFactory는 각각 Windows와 Mac 스타일의 버튼과 체크박스를 생성하는 IGUIFactory의 구체적인 구현체입니다. 클라이언트(Application)는 팩토리의 구체적인 클래스와는 독립적으로 동작하며, 테마에 따라 다른 팩토리를 사용해 필요한 제품군의 객체를 생성합니다. 이렇게 하면 테마가 변경되더라도 클라이언트 코드를 수정하지 않고도 원하는 GUI 스타일을 적용할 수 있습니다.
추상 팩토리 패턴의 장단점
장점
- 유지보수성과 확장성 증가: 클라이언트는 추상 인터페이스만 의존하기 때문에, 새로운 제품군을 추가하거나 기존 제품군을 변경해도 클라이언트 코드에 영향을 주지 않습니다.
- 코드 일관성 보장: 특정 제품군에 속하는 객체들이 일관성 있는 방식으로 생성됩니다.
- 객체 생성 로직의 캡슐화: 객체 생성 로직이 별도의 팩토리 클래스로 분리되므로, 클라이언트가 생성 로직을 알 필요가 없습니다.
단점
- 클래스 수 증가: 제품군마다 새로운 팩토리와 제품 클래스를 추가해야 하므로, 클래스 수가 많아져 복잡도가 증가할 수 있습니다.
- 변경 시 복잡성 증가: 제품군에 새로운 제품이 추가될 경우, 관련된 모든 팩토리와 제품 클래스를 수정해야 하므로 코드 변경이 다소 복잡할 수 있습니다.
언제 추상 팩토리 패턴을 사용해야 할까?
추상 팩토리 패턴은 관련된 여러 객체를 일관성 있게 생성해야 하는 경우에 적합합니다. 다음과 같은 상황에서 유용하게 사용할 수 있습니다.
- 서로 다른 환경에 맞춰 제품군을 생성해야 할 때: 예를 들어, Windows와 Mac 환경에 맞는 서로 다른 UI 요소를 생성할 때 유용합니다.
- 상호 관련된 객체 집합을 생성해야 할 때: 한 제품군의 객체가 다른 제품군의 객체와 상호작용할 때, 추상 팩토리를 사용하여 일관성을 유지할 수 있습니다.
- 클라이언트가 구체적인 클래스에 의존하지 않도록 설계할 때: 구체적인 클래스 대신 인터페이스와 추상 클래스를 통해 객체를 생성하여 코드의 유연성을 높입니다.
추상 팩토리 패턴과 팩토리 메소드 패턴의 차이점
추상 팩토리 패턴과 팩토리 메소드 패턴은 모두 객체 생성의 책임을 팩토리로 옮기는 생성 패턴이지만, 차이점이 있습니다.
- 팩토리 메소드 패턴은 단일 객체를 생성하는 데 중점을 두며, 각 클래스가 객체 생성을 관리하도록 상속을 통해 구조화합니다.
- 추상 팩토리 패턴은 관련된 객체 집합을 생성하는 데 중점을 두며, 한 팩토리에서 여러 객체를 관리합니다.
따라서, 단일 객체의 생성이 필요한 경우에는 팩토리 메소드 패턴을, 여러 제품군을 생성해야 할 경우에는 추상 팩토리 패턴을 선택하는 것이 적절합니다.
마무리하며
추상 팩토리 패턴은 여러 제품군을 생성하고자 할 때 제품군에 일관성을 유지하며, 코드의 유연성과 확장성을 높이는 데 유용합니다. 새로운 제품군이 추가되더라도 클라이언트 코드에 영향을 주지 않으므로 유지보수가 편리해지며, 다양한 환경에 맞는 객체 생성을 손쉽게 관리할 수 있습니다.
소프트웨어 설계에서 여러 제품군의 객체 생성을 일관성 있게 관리해야 할 때, 추상 팩토리 패턴을 활용해 보시기 바랍니다.
'Thinking > Concept' 카테고리의 다른 글
싱글턴 패턴(Singleton Pattern) 이해하기 (1) | 2024.11.14 |
---|---|
빌더 패턴(Builder Pattern) 이해하기 (1) | 2024.11.14 |
팩토리 메소드(Factory Method) 패턴 이해하기 (1) | 2024.11.14 |
개발자를 위한 필수 디자인 패턴 23가지 GoF 패턴 총정리 (0) | 2024.11.13 |
의사 코드(Pseudo Code)(슈도 코드, 가짜 코드)란? (0) | 2023.09.03 |