디자인 패턴

디자인 패턴에 대해 알아보자#4 - 팩토리 패턴 (Factory Pattern) (feat : 팩토리 메소드, 추상 팩토리 패턴)

근본넘치는개발자 2024. 10. 31. 23:40

오늘은 지난 시간에 이어 팩토리 패턴

(+ 팩토리 메소드, 추상 팩토리)에 대해 알아볼까 합니다.

 

 

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