오늘은 지난 시간에 이어 팩토리 패턴
(+ 팩토리 메소드, 추상 팩토리)에 대해 알아볼까 합니다.
2024.10.29 - [디자인 패턴] - 디자인 패턴에 대해 알아보자#3 - 전략 패턴 (Strategy)
팩토리 패턴이란 ?
객체 생성을 위한 패턴입니다.
팩토리라는 이름처럼 공장에서 상품을 찍어 내듯이
객체 생성을 전담하는 클래스를 통해 객체를 생성하는 패턴입니다.
이렇게 함으로써 객체 생성 로직을 캡슐화하고,
객체 생성과 사용을 분리할 수 있습니다.
예시
// 추상 제품 인터페이스
public interface ICharacter
{
void Attack();
void Move();
}
// 구체적인 제품 클래스들
public class Warrior : ICharacter
{
public void Attack()
{
Console.WriteLine("전사가 검으로 공격합니다!");
}
public void Move()
{
Console.WriteLine("전사가 뛰어갑니다.");
}
}
public class Archer : ICharacter
{
public void Attack()
{
Console.WriteLine("궁수가 활로 공격합니다!");
}
public void Move()
{
Console.WriteLine("궁수가 가볍게 이동합니다.");
}
}
public class Mage : ICharacter
{
public void Attack()
{
Console.WriteLine("마법사가 마법으로 공격합니다!");
}
public void Move()
{
Console.WriteLine("마법사가 순간이동합니다.");
}
}
// 팩토리 클래스
public class CharacterFactory
{
public ICharacter CreateCharacter(string type)
{
switch (type.ToLower())
{
case "warrior":
return new Warrior();
case "archer":
return new Archer();
case "mage":
return new Mage();
default:
throw new ArgumentException("Unknown character type");
}
}
}
// 사용 예제
public class Game
{
public void Run()
{
CharacterFactory factory = new CharacterFactory();
// 캐릭터 생성
ICharacter warrior = factory.CreateCharacter("warrior");
ICharacter archer = factory.CreateCharacter("archer");
ICharacter mage = factory.CreateCharacter("mage");
// 캐릭터 사용
warrior.Attack(); // 출력: 전사가 검으로 공격합니다!
archer.Move(); // 출력: 궁수가 가볍게 이동합니다.
mage.Attack(); // 출력: 마법사가 마법으로 공격합니다!
}
}
예시를 보니까 한눈에 이해가 가시나요?
여기까지는 기존에도 알고 있었는데
찾다 보니 팩토리 패턴의 확장된 형태가 있더군요.
팩토리 메소드 패턴과 추상 팩토리 패턴에 대해서도 정리해 봤습니다.
팩토리 메소드 패던
// 추상 클래스
public abstract class WeaponCreator
{
// 팩토리 메소드 - 서브클래스에서 구현
protected abstract IWeapon CreateWeapon();
// 템플릿 메소드
public void UseWeapon()
{
IWeapon weapon = CreateWeapon(); // 팩토리 메소드 호출
weapon.Attack();
Console.WriteLine("무기 사용 완료!");
}
}
// 구체적인 제품 클래스들
public class SwordCreator : WeaponCreator
{
protected override IWeapon CreateWeapon()
{
// 검 생성에 필요한 추가 로직
Console.WriteLine("새로운 검을 제작합니다...");
return new Sword();
}
}
public class BowCreator : WeaponCreator
{
protected override IWeapon CreateWeapon()
{
// 활 생성에 필요한 추가 로직
Console.WriteLine("새로운 활을 제작합니다...");
return new Bow();
}
}
// 사용 예제
public class WeaponExample
{
public void ShowDifference()
{
// 팩토리 메소드 패턴 사용
WeaponCreator swordCreator = new SwordCreator();
swordCreator.UseWeapon(); // 전체 프로세스 실행
}
}
추상 팩토리 패턴
// === UI 컴포넌트 인터페이스들 ===
public interface IButton
{
void Render();
void HandleClick();
}
public interface IPanel
{
void Display();
void SetBackground();
}
public interface IText
{
void Show();
void SetFont();
}
// === 라이트 테마 컴포넌트들 ===
public class LightButton : IButton
{
public void Render()
{
Console.WriteLine("하얀 배경에 검은색 버튼을 렌더링합니다.");
}
public void HandleClick()
{
Console.WriteLine("라이트 테마 버튼 클릭 효과를 재생합니다.");
}
}
public class LightPanel : IPanel
{
public void Display()
{
Console.WriteLine("밝은 색상의 패널을 표시합니다.");
}
public void SetBackground()
{
Console.WriteLine("패널에 밝은 배경을 설정합니다.");
}
}
public class LightText : IText
{
public void Show()
{
Console.WriteLine("검은색 텍스트를 표시합니다.");
}
public void SetFont()
{
Console.WriteLine("라이트 테마용 폰트를 설정합니다.");
}
}
// === 다크 테마 컴포넌트들 ===
public class DarkButton : IButton
{
public void Render()
{
Console.WriteLine("어두운 배경에 밝은색 버튼을 렌더링합니다.");
}
public void HandleClick()
{
Console.WriteLine("다크 테마 버튼 클릭 효과를 재생합니다.");
}
}
public class DarkPanel : IPanel
{
public void Display()
{
Console.WriteLine("어두운 색상의 패널을 표시합니다.");
}
public void SetBackground()
{
Console.WriteLine("패널에 어두운 배경을 설정합니다.");
}
}
public class DarkText : IText
{
public void Show()
{
Console.WriteLine("밝은색 텍스트를 표시합니다.");
}
public void SetFont()
{
Console.WriteLine("다크 테마용 폰트를 설정합니다.");
}
}
// === 추상 팩토리 인터페이스 ===
public interface IUIFactory
{
IButton CreateButton();
IPanel CreatePanel();
IText CreateText();
}
// === 구체적인 팩토리들 ===
public class LightThemeFactory : IUIFactory
{
public IButton CreateButton()
{
return new LightButton();
}
public IPanel CreatePanel()
{
return new LightPanel();
}
public IText CreateText()
{
return new LightText();
}
}
public class DarkThemeFactory : IUIFactory
{
public IButton CreateButton()
{
return new DarkButton();
}
public IPanel CreatePanel()
{
return new DarkPanel();
}
public IText CreateText()
{
return new DarkText();
}
}
// === UI 관리자 클래스 ===
public class UIManager
{
private readonly IUIFactory uiFactory;
private IButton button;
private IPanel panel;
private IText text;
public UIManager(IUIFactory factory)
{
uiFactory = factory;
}
public void CreateUI()
{
button = uiFactory.CreateButton();
panel = uiFactory.CreatePanel();
text = uiFactory.CreateText();
}
public void RenderUI()
{
panel.SetBackground();
panel.Display();
button.Render();
text.Show();
}
}
// === 사용 예제 ===
public class ThemeExample
{
public void ShowThemeSystem()
{
// 라이트 테마 UI 생성
Console.WriteLine("=== 라이트 테마 UI ===");
IUIFactory lightFactory = new LightThemeFactory();
UIManager lightUI = new UIManager(lightFactory);
lightUI.CreateUI();
lightUI.RenderUI();
Console.WriteLine("\n=== 다크 테마 UI ===");
// 다크 테마 UI 생성
IUIFactory darkFactory = new DarkThemeFactory();
UIManager darkUI = new UIManager(darkFactory);
darkUI.CreateUI();
darkUI.RenderUI();
}
}
정리
팩토리 패턴 :
조건문으로 객체 생성
팩토리 메소드 패턴 :
추상 클래스를 활용하여 한 종류의 객체 생성
추상 팩토리 패턴 :
관련된 여러 객체의 집합을 생성
마무리
오늘은 팩토리 패턴과,
여기서 확장된 추상 팩토리 패턴 / 팩토리 메소드 패턴에 대해 알아보았습니다.
전략 패턴과 마찬가지로 은연중에 자주 봐 왔던 패턴이었네요.
다만 팩토리 메소드 패턴과 추상 팩토리 패턴이라는 건 처음 들어봐서 정리해 봤는데
영상에서 언급한 것처럼 굳이 이름을 나눠야 했나 싶긴 하네요.
아무튼 기억해 두었다가 적용해 봐야겠습니다.
팩토리 패턴에 오브젝트 풀이나 싱글톤을 응용한다고 하는데
이건 아직 제 수준에서는 어렵네요. 동적으로 관리하는 것도 있고.;;
참고한 자료
https://www.youtube.com/watch?v=qhtL9EYtB3Q&t=368s
'디자인 패턴' 카테고리의 다른 글
디자인 패턴 - MVC(Model-View-Controller)패턴에 대해 알아보자(+ MVP, MVVM) (0) | 2024.11.07 |
---|---|
디자인 패턴에 대해 알아보자#5 옵저버 패턴 (Oberserver) (0) | 2024.11.05 |
디자인 패턴에 대해 알아보자#3 - 전략 패턴 (Strategy) (0) | 2024.10.29 |
디자인 패턴에 대해 알아보자#2 싱글톤 패턴(feat. 유니티) (1) | 2024.10.08 |
디자인 패턴에 대해 알아보자 #1 Solid 원칙 (0) | 2024.10.07 |