Dev Base

[Dev Base] 디자인패턴_구조패턴

Yangho 2025. 4. 19. 15:14

1. 어댑터 패턴 (Adapter Pattern)

개요

어댑터 패턴은 호환되지 않는 인터페이스를 맞춰주는 역할을 한다. 기존 클래스를 변경하지 않고 새로운 인터페이스에 적응시키는 방식이다.

목적

  • 서로 다른 인터페이스를 사용하는 클래스 간의 호환성 확보
  • 레거시 코드 재사용

구조

// 기존 클래스
class OldSystem
{
    public void OldRequest() => Console.WriteLine("Old request");
}

// 새 인터페이스
interface INewSystem
{
    void Request();
}

// 어댑터
class Adapter : INewSystem
{
    private OldSystem oldSystem = new OldSystem();
    public void Request() => oldSystem.OldRequest();
}

장점

  • 기존 코드 변경 없이 사용 가능
  • 인터페이스 호환 문제 해결

단점

  • 코드가 복잡해질 수 있음

사용 예시

  • 외부 라이브러리 인터페이스 통합
  • 게임에서 기존 입력 시스템을 새 입력 시스템에 맞출 때


2. 브리지 패턴 (Bridge Pattern)

개요

브리지 패턴은 구현과 추상화를 분리하여 서로 독립적으로 확장할 수 있도록 한다.

목적

  • 구현부와 추상부를 분리하여 독립적 확장 가능
  • 클래스 수 증가 억제

구조

interface IRenderer
{
    void Render(string shape);
}

class CircleRenderer : IRenderer
{
    public void Render(string shape) => Console.WriteLine($"Draw circle: {shape}");
}

abstract class Shape
{
    protected IRenderer renderer;
    public Shape(IRenderer renderer) { this.renderer = renderer; }
    public abstract void Draw();
}

class Circle : Shape
{
    public Circle(IRenderer renderer) : base(renderer) { }
    public override void Draw() => renderer.Render("Circle");
}

장점

  • 추상화와 구현부를 독립적으로 확장 가능
  • 유연한 구조

단점

  • 구조가 복잡할 수 있음
  • 초기 설계 비용이 높음

사용 예시

  • 게임에서 다양한 렌더링 방식 지원
  • UI 플랫폼 추상화

3. 컴포지트 패턴 (Composite Pattern)

개요

컴포지트 패턴은 부분-전체 계층 구조를 동일하게 처리할 수 있도록 구성하는 패턴이다.

목적

  • 단일 객체와 복합 객체를 동일하게 취급

구조

abstract class UIElement
{
    public abstract void Render();
}

class Button : UIElement
{
    public override void Render() => Console.WriteLine("Render Button");
}

class Panel : UIElement
{
    private List<UIElement> children = new List<UIElement>();
    public void Add(UIElement child) => children.Add(child);

    public override void Render()
    {
        Console.WriteLine("Render Panel");
        foreach (var child in children)
            child.Render();
    }
}

장점

  • 트리 구조 구성에 유리
  • 일관된 처리 가능

단점

  • 설계가 복잡해질 수 있음

사용 예시

  • 게임 UI 계층 구성
  • 씬 그래프 트리 구조


4. 데코레이터 패턴 (Decorator Pattern)

개요

데코레이터 패턴은 기존 객체에 기능을 동적으로 추가하는 구조이다.

목적

  • 상속 없이 객체에 기능 추가
  • 실행 중 기능 확장 가능

구조

interface IWeapon
{
    void Attack();
}

class Sword : IWeapon
{
    public void Attack() => Console.WriteLine("Swing sword");
}

class FireDecorator : IWeapon
{
    private IWeapon weapon;
    public FireDecorator(IWeapon weapon) { this.weapon = weapon; }
    public void Attack()
    {
        weapon.Attack();
        Console.WriteLine("with Fire");
    }
}

장점

  • 런타임 동적 확장
  • 조합 가능한 기능 확장

단점

  • 많은 데코레이터 조합 시 복잡도 증가
  • 디버깅 어려움

사용 예시

  • 게임에서 무기 강화 시스템
  • UI 요소에 효과 추가


5. 퍼사드 패턴 (Facade Pattern)

개요

퍼사드 패턴은 복잡한 서브 시스템을 단순한 인터페이스로 감싸는 방식이다.

목적

  • 복잡한 시스템 사용을 쉽게 함
  • 클라이언트와 서브 시스템 간 결합도 감소

구조

class AudioSystem
{
    public void Init() => Console.WriteLine("Audio Init");
}

class RenderSystem
{
    public void Init() => Console.WriteLine("Render Init");
}

class GameEngine
{
    private AudioSystem audio = new AudioSystem();
    private RenderSystem render = new RenderSystem();

    public void Start()
    {
        audio.Init();
        render.Init();
    }
}

장점

  • 사용이 간편
  • 내부 구현 캡슐화

단점

  • 퍼사드에 너무 많은 책임이 집중될 수 있음

사용 예시

  • 게임 엔진 초기화 코드
  • 외부 API 통합


6. 플라이웨이트 패턴 (Flyweight Pattern)

개요

플라이웨이트 패턴은 공통된 데이터를 공유하여 메모리를 절약하는 구조이다.

목적

  • 메모리 사용 최소화
  • 수많은 객체 생성을 효율적으로 처리

구조

class TreeType
{
    public string Name;
    public string Texture;
}

class Tree
{
    public int X, Y;
    public TreeType Type;
}
 

장점

  • 메모리 사용 감소
  • 대규모 객체 처리에 적합

단점

  • 상태와 공유 데이터 분리 필요
  • 코드 복잡도 증가

사용 예시

  • 수많은 배경 오브젝트가 반복되는 게임
  • 캐릭터 외형 데이터 공유

7. 프록시 패턴 (Proxy Pattern)

개요

프록시 패턴은 다른 객체에 대한 접근을 제어하는 대리 객체를 제공하는 구조이다.

목적

  • 접근 제어, 지연 초기화, 캐싱 등 기능 추가

구조

 
interface IImage
{
    void Display();
}

class RealImage : IImage
{
    public void Display() => Console.WriteLine("Display real image");
}

class ProxyImage : IImage
{
    private RealImage realImage;

    public void Display()
    {
        if (realImage == null)
            realImage = new RealImage();
        realImage.Display();
    }
}

장점

  • 접근 제어 용이
  • 자원 낭비 방지

단점

  • 설계 복잡성 증가

사용 예시

  • 게임 리소스의 지연 로딩
  • 네트워크 객체 프록시