객체 생성시 즉, 캐스팅 관계는 다음과 같다.

부모를 두고 자식이 부모 = 자식, 부모 = 부모, 자식 = (자식)부모 캐스팅 가능하나 자식 = 부모 캐스팅은 안된다.

이것은 OOP를 해 본 사람이라면 당연히 알 것이다.

이 글을 쓴 것도 훈스에 놀러 갔다가 퇴근5분전 님이 올린 댓글을 보고 그냥 생각나서 끄적여 본다.

흔히들 패턴에 맞춰서 코드를 생성하다 보면 함정에 빠진다.

당연히 1번과 2번의 관계면 생성 되서 다형성 형태로 만들 수 있겠지 하는 그런 생각.

그렇다고 함정에 빠지는 사람이 많다고 생각하지 않는다. 상속 관계를 어느정도 이해를 하는 사람들은...

하지만 다형성을 구현하고 할 경우에는 항상 숙지 해 둬야한다고 생각한다.
컴파운드 패턴은 여러 상황에 대해서 두개 이상의 패턴이 어우러진 디자인 패턴을 말한다.

프로젝트를 진행하다보면 여러가지 패턴들을 적용 시킬 수 있는데,

그 패턴들의 조합을 지칭하는 패턴이다.

언젠가 고수가 되면.. 무결성이 있는 그런 패턴을 만들지 않을까...
스테이트 패턴. 스트레티지랑 동일한 클래스 구조를 가지고 있다.

하지만 차이점은 분명하다.

스트레티지의 경우 그 행동에 대한 내용을 정의 해서 각기 객체에 전달하여 그 내용을 실행하지만,

스테이트의 경우는 실행 중 그 내용에 따라 각기 행동에 맞게 바꿀 수가 있따.

하나의 전환 흐름을 판단 할 수 있게 모든 행동 패턴들은 관리자로 넘어온다.(Context 객체)

그 관리자에서 취합한 정보들을 가지고 각기 행동에 대한 맞는 객체를 전달하여 기능을 실행한다.


컴포지트 패턴..

객체들을 각기 트리 구조로 구성하여 복합 객체를 서로 다른 객체들을 같은 방법으로 접근 가능하게 한다.

단순한 트리 구조에 상위 노드에 정보를 모두 모아두고 그 내용들을 이터레이터를 이용하여 뽑아내어 쓴다.

B-TREE 를 생각하면 안되고 하나의 부모에 여러 LEAP가 달린 구조를 생각하면 이해가 쉬울 것이다.

이터레이터 패턴.. 말 그대로 반복자이다.

개별적으로 반복자를 만들어서 그 내용을 외부로  노출시키지 않고 각 항목에 접근이 가능하다.

일단 코드로 구현은 해 봤지만 상황에 따라 다르고 한다고 해도 C#에서 제공해주는

IEnumerator를 이용하는게 좀 더 편하다고 느껴진다.

뭐.. 상황에 따라서 다르겠지만 지금 당장은 그렇다는 생각이 강하게 든다.

 


기본적인 알고리즘 골격을 잡는 것에 좋다.

일부는 추상 클래스 내에서 구현을 하고, 일부는 상속받는 클래스 내에서 구현을 할 수가 있다.

기본적인 추상 클래스를 이용하여 짤 경우 많이 볼 수가 있다.

얼추보면 팩토리 패턴과 비슷한 느낌이기는 하나, 최상위 클래스 내에 그 행동들을 실행하는 템플릿 메소드가 존재한다.

뭐.. 단지 이런 차이가 아닐까 라는 생각도 든다.

팩토리 메소드 경우는 중간에 클래스를 두고 각기 해당하는 내용들에 대해서 처리 할 수 있지만

템플릿 메소드의 경우 각 해당하는 부분 부분을 나눠서 구현이 가능하고, 그 실행 주체를 최상위 클래스에 둔다는 점에서 다른 듯 하다.


퍼사드 패턴..

뭐랄까..

그냥 나누어진 기능 덩어리를 한 클래스에 다 넣어놓고

각기 해당하는 기능의 메소드를 따로 정의 하여 그놈을 호출하면 된다.. 라는 느낌이 강하게 든다.

리모컨을 생각해보면 리모컨 안에는 많은 기능들이 있다.

그 기능을 감싸고 있는건 리모컨 박스..

그 안에서 각기 해당하는 놈들을 작동 시킨다고 생각하면 이해가 더 빠를거 같다.

즉 어떤 하위 시스템의 기능을 통합한 인터페이스를 제공하느 방식이다.

퍼사드는 이게 전부이다.

여기에서 보면 Mp3와 Movie가 하위 시스템이다

Facade 내부에는 이 모든 것을 포함하고 있고

클라이언트에서는 Facade 내부의 해당하는 메소드를 이용하여 각기 그 기능을 실행한다.


어댑터 패턴.

어릴적.. 110V 콘덴서가 기억이 난다.

220V 바뀌고 난 다음 어쩔 수 없이 110V 연결 위에서 콘덴서를 이용 했던 적이!!

그 콘덴서가 바로 Adapter 역할을 하는 것이다.

하나의 인터페이스를 타겟으로 할 경우에는 Adapter Pattern을 이용하면 좋다.

여러 상황을 보면 다중 어댑터를 구현 해야 할 경우도 있다.


Turkey를 어댑터를 이용하여 Duck 로 변환하고자 할 경우

Duck duck = new U_adapter() 방식으로 변환하여 쓴다.

물론 U_adapter에는 그에 맞게 행동하는 내용들이 변환된 호출한 내용을 포함을 한다.


커맨드 패턴은 각각의 요구 사항을 캡슐화 하여 그 내용을 실행 시키게 한다.

예를 들어 불을 켜거나 끌 때에 각기 해당 내용이 실행되는 것을 생각해보면 될 것이다.

전문적인 용어 상황에서 본다면

클라이언트의 요구에 의해 인보커는 그 요청에 대한 내용을 실행하도록 리시버에 요청을 하면 리시버는 그 내용을 실행한다.

커맨드 패턴은 주로 스케쥴러, 스레드 풀, 큐 같은 용도에서 쓸 수가 있고

순차적으로 이루어진 작업임으로 이 전 데이터로 돌리기도 쉬운편이다.


Main에서 먼저 Remote(인보커)를 생성하고, 그 후 리시버(Command)에 특정 행동들을 요구한다(Lignt, Door).

VS2008에서의 다이어그램 구성은 저기 까지 나옴으로 샘플을 참조하는 것이 좋을 것 같다.

싱글톤 패턴..

유일하게 하나의 정의만 있어야 하는 패턴이다.

일반적으로 우리가 쓰는 싱글톤은 다음과 같이 쓸 것이다.

Object m_obj;
Object _obj
{
    get
       {
           if(m_obj==null)
              m_obj = new Object
           return m_obj;
       {
}

하지만 여기에서 문제가 있다.

멀티스레드에 의해서 생기는 문제로 동기화가 되지 않아 여러번 생성이 된다는 경우가 종종 생긴다.

그럴 경우에는 분명 데이터가 뒤죽 박죽으로 흘러 갈 것이다.

그 다음으로 쓰는 방법이 아마 일반적으로 static 을 이용 할 것이다.

static Object m_obj;
static Object _obj
{
    get
       {
           if(m_obj==null)
              m_obj = new Object
           return m_obj;
       {
}

이는 어느 정도 문제를 해결해 주지만 한번도 쓰이지 않을 경우 메모리만 선점하고 있다는 문제가 생긴다.

필자도 저 방식으로 종종 쓰는 경우가 많다(쓰레드 환경 제외)

멀티쓰레드라면 아마 이 방법이 제일 좋을 것 같다. lock 키워드를 이용하는 것이다.

(lock은 monitor와 같이 동기화를 이용 할 때 쓰는 키워드이다.)

static Object m_obj;
static Object _obj
{
    get
       {
           if(m_obj==null)
              lock(m_obj)
              {
                 m_obj = new Object
              }
           return m_obj;
       {
}

이 방법은 인스턴트 생성시 걸리는 시간 때문이다. 이렇게 lock을 걸어 둔다면 멀티쓰레드 환경 상에서는 최소한의 속도가 유지 될 것이다.