프로그래밍/ 디자인 패턴

Singleton Pattern

class Singleton 
{
    private static Singleton instance;
    public static Singleton Instance
    {
        get 
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }

    // 클래스 몸체...
}
  • 프로그램 내에서 단 하나의 인스턴스만 존재하는 경우에 사용. ex) 시간 관리.
  • 객체가 생성되지 않은 상태에서도 접근 가능해야 하므로 –null이면 그때 생성한다– 변수는 static으로 선언한다.
  • 외부에서 클래스에 접근할 때는 Singleton.Instance를 통해 접근한다.
    • 위의 예는 C#의 프로퍼티를 이용한 코드인데, 자바 같은 경우는 getInstance()와 같은 별도의 메소드를 만들기도 한다.

Observer Pattern

델리게이트를 이용한 방식

class Publisher
{
    public delegate void MyEventHandler(); 
    private event MyEventHandler onClick;

    public void AddSubscriber (MyEventHandler Subscriber)
    {
        onClick += Subscriber;
    }

    public void DoClick()
    {
        if(onClick != null)
        {
            onClick(); 
        }
    }
}
  • 함수 포인터가 없어서 Observable 을 상속 받아 구현해야 하는 자바와 달리 C#은 델리게이트 자체가 옵저버 패턴을 담고 있기 때문에 매우 편리하게 옵저버 패턴을 사용할 수 있다.
    • 위의 예는 델리게이트에 event 한정자를 추가로 사용하고 있는데, 일반 델리게이트 체인은 외부에서 접근 가능한 반면 event 한정자를 받으면 외부에서 접근이 불가능해지므로 보다 캡슐화된 구조를 가질 수 있다.

Generics을 이용한 방식

// List를 이용한 방식
class PublisherList
{
    private List<Action> list = new List<action>();

    public void AddSubscriber (Action Callback)
    {
        list.Add(Callback);
    }

    public void DoClick()
    {
        foreach (var callback in list)
        {
            callback();
        }
    }
}

// Dictionary를 이용한 방식
class PublisherDictionary
{
    private Dictionary<string, Action> dict = new Dictionary<string, Action>();

    public void AddSubscriber (string Key, Action Callback)
    {
        dict[Key] = Callback;
    }

    public void DoClick()
    {
        foreach (var kvp in dict)
        {
            kvp.Value();
        }
    }
}
  • Generic의 List를 이용한 방식은 Event를 이용한 방식과 사실 차이는 없다. 위의 예시는 보여주기 위한 것일 뿐. 그런데 만일 Dictionary를 이용해서 Callback을 관리한다면, Dictionary에 함께 들어가는 Key를 이용해서 특정 Key만 Notify를 알릴 수도 있다.

Factory Method Pattern

abstract class WeaponFactory
{
    public abstract void Fire ();

    // 클래스 몸체...
}

class pistol : WeaponFactory
{
    public override void Fire ()
    {
        // 권총 발사
    }
}

class Arrow : WeaponFactory
{
    public override void Fire ()
    {
        // 화살 발사
    }
}
  • 여러 상이한 클래스들 사이에 공유되는 기능이 많은데 어느 한 부분만 개별적으로 구현해 줘야하는 경우, 공통된 부분을 상위 클래스로 묶고 개별적으로 구현해 줘야 하는 부분만 override 해서 구현하게 한다.
    • 사실 이것도 그렇고 하위에서 자체 메소드를 이용해서 필드의 값을 가져오게 하는 데코레이터 패턴도 그렇고 굳이 패턴이라고 따로 뺄 필요가 있나 싶다.
[ssba]

The author

지성을 추구하는 디자이너/ suyeongpark@abyne.com

댓글 남기기