카테고리 없음

Bridge Pattern

iamreo 2013. 7. 23. 12:58
반응형

일반적인 클래스 설계


우리는 유닛 클래스를 설계해야 합니다.
이 유닛은 마린과 매딕이 존재합니다.
마린은 총을 쏘고 매딕은 주사기로 치료를 합니다.


abstract class 유닛{
    void 무기사용();
}

class 마린 : 유닛{
    void 무기사용(){총.사용하기();}
}

class 매딕 : 유닛{
    void 무기사용(){주사기.사용하기();}
}

class 총{
    void 사용하기(){발사;}
}

class 주사기{
    void 사용하기(){치료;}
}



클라이언트의 요구사항


마린도 주사기를 사용하고 매딕도 총을 사용할 수 있게 하고 싶다는 요구사항이 들어왔습니다.
그래서 상속을 이용해 아래와 같이 해결하였습니다.


abstract class 유닛{
    void 무기사용();
}

class 마린 : 유닛{
    void 무기사용();
}

class 매딕 : 유닛{
    void 무기사용();
}

class 총쏘는마린 : 마린{
    void 무기사용(){총.사용하기();}
}

class 치료하는마린 : 마린{
    void 무기사용(){주사기.사용하기();}
}

//총쏘는매딕과 치료하는매딕의 구현은 생략

class 총{
    void 사용하기(){발사;}
}

class 주사기{
    void 사용하기(){치료;}
}



그런데 다시 새로운 요구사항이 들어왔습니다.

새로 추가된 요구사항



  1. 파이어뱃의 추가 - 화염방사기를 사용함

  2. 고스트의 추가 - 총을 사용함

  3. 치료하는 파뱃, 총쏘는 파뱃, 치료하는 고스트, 화염방사기 마린...등의 구현이 필요



처음 요구사항을 해결한 방식으로 추가된 요구사항을 해결할 수 있지만 유닛과 무기가 늘어날 수록 클래스의 숫자는 폭발적으로 늘어나게 됩니다.
우리는 이 문제를 디자인 패턴을 이용하여 해결하려 합니다.

Bridge 패턴이란?




사전적인 의미

추상화 개념과 구현을 분리하여 독립적으로 변화할 수 있도록 한다

패턴을 적용할 상황

파생 클래스의 폭발적 증가 없이 다양한 구현이 필요한 상황



'알기쉬운 디자인 패턴'에 나오는 'Bridge 패턴'은 다음과 같은 기본 전략을 따르고 있습니다.


  • 무엇이 변경되는지 찾아내고 그것을 캡슐화하자

  • 상속보다는 합성을 쓰도록 노력하자



위의 내용들이 지금 당장 이해되지 않더라도 괜찮습니다.
차근차근 풀어나가 보겠습니다.

Bridge 패턴의 적용


위에서 발생한 요구사항에 따른 문제는 'Bridge 패턴'을 적용할 상황(파생 클래스의 폭발적 증가 없이 다양한 구현이 필요한 상황)에 걸맞습니다.
사전적 의미는 일단 배제하고 두가지 기본 전략을 통해 위의 예제를 분석하겠습니다.

우선 첫번째 '무엇이 변경되는지 찾아내고 그것을 캡슐화하자'
위의 예제에서 변경되는 것은 유닛이 [마린과 매딕]으로, 무기가 [총과 주사기]로 변경됩니다.
마린과 매딕은 그대로 유닛으로 두고 총과 주사기를 무기화 시킵니다.


abstract class 무기{
    void 사용하기();
}

class 총 : 무기{
    void 사용하기(){발사;}
}

class 주사기 : 무기{
    void 사용하기(){치료;}
}




두번째 전략 '상속보다는 합성을 쓰도록 노력하자'를 적용해 보겠습니다.
합성이란 것은 복잡한 것이 아니라 하나의 클래스가 다른 클래스를 포함하여 사용하게 하는 것입니다.
그렇다면 '무기가 유닛을 사용하는 것'과 '유닛이 무기를 사용하는 것'중 무엇이 맞을까요?
당연히 유닛이 무기를 사용하는 것이 맞겠죠.


//무기 클래스를 사용하도록 변경된 유닛관련 클래스
abstract class 유닛{
    무기 arms;
    유닛(무기 a){arms = a}; //생성자
    void 무기사용(){arms.사용하기();}
}

class 마린 : 유닛{
    마린(무기 a){super(a);} //생성자, super는 부모클래스
}

class 매딕 : 유닛{
    매딕(무기 a){super(a);} //생성자, super는 부모클래스
}

//무기관련 클래스는 변경사항 없슴
abstract class 무기{
    void 사용하기();
}

class 총 : 무기{
    void 사용하기(){발사;}
}

class 주사기 : 무기{
    void 사용하기(){치료;}
}



생성자를 통해서 무기를 인수로 받고 유닛 클래스의 파생 클래스(마린과 매딕)는 무기의 종류는 모르지만 사용합니다.
위의 클래스를 이용한 간단한 예제를 만들어 보겠습니다.


무기 arms = new 총();
유닛 marine = new 마린(arms);

marine.무기사용();



마린이 주사기를 사용하는 것도 문제 없겠죠?

패턴이 적용된 모습에 대한 분석


위에서 'Bridge 패턴'의 사전적 의미는 "추상화 개념과 구현을 분리하여 독립적으로 변화할 수 있도록 한다" 였습니다.
패턴의 적용으로 아래와 같은 구조를 가지게 되었습니다.

[유닛]-[마린,매딕] ---사용---> [무기]-[총,주사기]

추상화 개념은 유닛이 마린과 매딕으로 분류된다는 것이고 유닛이 무기사용에 대한 구현을 무기클래스로써 분리한 것입니다.

요구사항 해결하기


이제 'Bridge 패턴'을 적용한 클래스 설계에 새로 추가된 요구사항을 적용해 보겠습니다.


abstract class 유닛{
    무기 arms;
    유닛(무기 a){arms = a}; //생성자
    void 무기사용(){arms.사용하기();}
}

class 마린 : 유닛{
    마린(무기 a){super(a);} //생성자, super는 부모클래스
}

class 매딕 : 유닛{
    매딕(무기 a){super(a);} //생성자, super는 부모클래스
}

class 파이어뱃 : 유닛{
    파이어뱃(무기 a){super(a);} //생성자, super는 부모클래스
}

class 고스트 : 유닛{
    고스트(무기 a){super(a);} //생성자, super는 부모클래스
}

abstract class 무기{
    void 사용하기();
}

class 총 : 무기{
    void 사용하기(){발사;}
}

class 주사기 : 무기{
    void 사용하기(){치료;}
}

class 화염방사기 : 무기{
    void 사용하기(){태우기;}
}



'알기쉬운 디자인 패턴'에서의 예제는 저의 예제와 다릅니다. 책의 예제는 Adapter 패턴도 혼합되어 있습니다.
'Bridge 패턴'에 대한 설명은 이로써 마치겠습니다.
최대한 쉽고 짧게 쓴다고 노력했는데 'Bridge 패턴'을 이해하는데 도움이 되었을지 궁금하네요.
'Bridge 패턴'을 더욱 자세하게 공부하시고 싶으시다면 반드시 책을 참고하시기 바랍니다.


출처 : http://ani2life.egloos.com/2904131

이렇게 정리를 하는 님들의 열정에 정말.... 감동받습니다.

그 어떤 사실을 떠나, 박수~~~

반응형