관리 메뉴

HAMA 블로그

꼬리에 꼬리를 무는 - 유사 디자인 패턴들 - (3,4) 본문

디자인패턴

꼬리에 꼬리를 무는 - 유사 디자인 패턴들 - (3,4)

[하마] 이승현 (wowlsh93@gmail.com) 2017. 7. 8. 23:54

 

꼬리에 꼬리를 무는 - 유사 디자인 패턴들

 (3/4편)

 

 

패턴을 공부하거나 할 때 UML 에 집중해서 공부하면 안된다고 생각한다. 구조만을 외우고 구조로 구분을 한 사람은  공부한것을 금방 까먹거나 헤깔려하기 쉽기 때문인데, 이유는 거의 비슷한 구조를 갖춘 패턴들은 정말 많기 때문이다. ( 더 헥깔린것은 동일 패턴이 구조가 다른 경우도 부지기수이다. 의도가 같기 때문. 즉 "의도", "목적" 이 중요하다.) 

아래 구조를 보자.

정말 많지 않나?? 이 구조만 보고 뭘 알 수 있을까? 자신이 Composite 패턴만 공부했다면 , 이러한 구조를 보고 무조건 "컴포지트 패턴" 이라고 어디가서 우기지나 않을까 염려된다.

 

이런 식 또한 많다. 무엇인가?? 당연히 알수가 없다.
또한 저런 동일한 구조에 여러 패턴이 같이 참여 할 수 도 있다. 예를들어 Strategy패턴과 Flyweight 패턴이 같은 클래스들을 공유하는 경우가 실제 세계에는 부지기수로 일어나기도 한다. 그럴 때는 A 클래스와 B 클래스는 OO 패턴 과 XX 패턴에 어떤 역할로 참여하고 있다 라고 말하며 회의시에 커뮤니케이션 할 수 있겠다. 

따라서 앞으로 나올 패턴 비교에서는 UML 에 대한 설명은 하지 않으며  그냥 말로 "의도" 를 전달 할 예정이다.
마지막으로 디자인패턴을 처음 공부하는 사람을 위한 글은 아니며, 대략 공부한 상태에서 정리하기 위한 목적의 글이라는 점을 양해 드린다. 

 

1,2편은 여기에 -> http://hamait.tistory.com/868

3. Adapter 패턴 vs Facade 패턴

자 이전 글에서 어댑터 패턴에 대해서 알아보았다. 남의 인터페이스를 내 설계에 맞춰서 사용하고 싶을 때 사용한다는것을 알았는데, Facade 도 비슷하지 않을까? Facade 는 건물의 출입구 쪽의 외벽을 말하는 것으로 소프트웨어 디자인 패턴에서는 감추어져 있는 건물(서비시스템등) 의 안을 들어가서 샅샅히 탐험 할 필요 없이, 출입구에서 심플하게 처리하겠다는 의미를 가지고 있다. 즉 내부에서 일어나는 복잡한 행동들을 이해할 필요 없이 중간 매개체에서 한방에 모든게 해결되게 하자는 뜻이다. 

결국 자신과 타인 사이의 중간 지점에서 타인의 기능을 사용한다는 느낌에서는 두 패턴이 비슷하지만, 

 어댑터 패턴은 중간에서 남의 인터페이스를 자신의 인터페이스의 모양으로 "인터페이스의 변경"  하기 위함이 목적이라면  Facade 는 서비시스템의 복잡한 기능을 중간에서 감추고 심플하게 통신하자는것 (단방향) 이 목적이다. 

이제 UML 을 보자.

 

먼가 느낌오지 않는가? 제발 느낌만 받아드려라~

패키지가 뭐지~ 저런 화살표가 뭐지? 이런것은 잊어버리시고~ 그냥 그 느낌 그대로 해당 언어에 맞게 구현하면그게 Facade 이다. 혹시 구조가 그게 아닐까봐 눈치보지마라~ 구조가 어쨋든 상관없으니~ (언어마다 해당 언어의 이디엄이나 패러다임에 따라서 좀 달라 질 수도 있을 것이다) 

4. Facade 패턴 vs Brigde 패턴

자  이제 위에서 어댑터 패턴과 퍼사드패턴에 대해서 알아보았다. 어댑터 패턴도 퍼사드도 중간에서 먼가 하는 거 같다. 근데 중간?? 강남과 강북을 잇는 한강다리... Bridge ?? 중간에서 뭘 하는 느낌을 주는 것은 Bridge 패턴도 빼놓을 수는 없지 않겠는가~

그럼 브리지 패턴은 그 패턴들과 무엇이 다른것일까? 중간에서 뭘 하긴 하는데 그 동안 다룬 패턴들이 안 다룬게 무엇이 있을가 먼저 생각해보라~ 패턴이란 것은 다 생활에서 항상 일어나는 일을 정리한 것이니 분명히 생각해 낼 수도 있을 것이다. 

* Adapter 는 중간에서 인터페이스 변환

* Facade 는 중간에서 외부 모듈의 사용을 단순화 

* Proxy 는 중간에서 대리하여 기존 구현을 다른 방식으로 컨트롤 

* Decorator 는 중간에서 기존 구현에 다른 구현을 추가 

Facade 가 복잡성을 감추는게 목적이라면 Bridge 는 상대방의 구현들을 직접 사용하면 강합 결합도가 발생하기 때문에 중간에서 매개체 삽입!! 좀 더 있어보이게 말하면 서브시스템(외부 모듈)의 구현으로부터 레이어를 두어 "디커플링/유연성증가"  를 하기 위한 의도가 강하다.

사실 의도는 확 와닿긴 하지만 , 구조 잡을 때 어떻게 해야 할지 가장 선택의 폭이 큰 패턴 중 하나인거 같다.
따라서 어려우며, 일반 디자인 패턴들 보다는 큰 범위의 설계라고 볼 수 있다. (Abactract Factory 와 같이 아키텍처 급 )

이제 UML 을 보는데, 여기서는 UML 에 대해서 좀 자세히 설명해야 할 것 같다.

* 위의 UML 은 디자인패턴의 풍운아~ 본좌~구루이신 홀럽님의 패턴책에서 발췌된 것이다. 

집중해보자!! 

Client Class 는 Abstaraction 역할로써 호출자(User)는 이 추상객체를 이용해서 실제 서비스를 호출하게 된다.  이 그림에서는 좀 헦깔리게 Client 가 Abstraction 이다. Client (User) -> Abstraction 이런 그림이면 더 이해하기 쉬웠을듯~

Java.sql.Connection 등은 Implementor 로써 실제 서비스에 대한 인터페이스이다. 위의 Abstraction 은 보통 이 인터페이스를 통해 실제 시스템 구현과 대화이며  이 인터페이스는 보통 Abstract Factory 패턴에서 Abstract Product 역할을 하기도 한다.

com.holub.database.JDBCConnection 등은 위의 Implementor 를 구현한 실제 시스템이다. 보통 Abstract Factory 패턴에서 Concrete Product 역할을 하기도 한다.

 
 그렇다 뭔가 복잡해 보이지만 사실 그냥 중간에 Abstraction 이라는 녀석 하나 만들고 이 녀석이 다양한 구현체들을 상황에 맞춰서 유연하게~ 호출 할 수 있게 해준다는것이다. 위에서 Client 는 Java.sql.Connection 인터페이스에 대해 호출 했지만, Samba.sql.Connection 을 호출 할 수도 있겠고~ 유연함이 목적이니깐~

 

이번엔 꽤나 단순한 Bridge 패턴의 UML 이다. 별거 없지 않나? 그냥 오른쪽의 서브시스템 구현과 Client 를 Abstraction 을 이용해서 분리 시키는 것일 뿐이다. Client 는 오른쪽 서브시스템의 구현이 어떻게 변하더랴도 영향을 받지 않게 된다. 그 반대도 마찬가지~  "단순하게 구현하건 복잡하게 구현하건 의도가 그렇다면 그건 같은 패턴이된다."

 

5. Facade vs Mediator 패턴 

->  두 패턴 모두 복잡한 시스템간의 관계를 단순화 시켜준다. Facade 가 단방향이라면 Mediator 는 양방향의 통신에 대해 중간에서 다리역할을 해준다. 이때 Mediator 가 너무 많은 역할을 하게 될 수 가 있는데 경계해야 할 것이다.

6. Mediator vs Bridge 패턴 

-> 두 패턴 모두 서브시스템 간의 결합도를 줄여준다. Bridge 이 외부 시스템과의 유연성 증가를 위한 것이라면,  Mediator 는 다양한 객체간의 관계를 중간에서 정리해주는 역할 즉 복잡성을 감추기 위한 의도가 강하다. Bridge 가 무엇인가 생략하지 않고, 표준인터페이스를 통한 연결다리를 놔 준다면, Mediator 는 시스템 전반에 나타나는 복잡한 코드를 단순한 인터페이스로 통일 시켜준다. 그런 복잡성 감소의 목적에서는 Facade 와 비슷하다. 

7. Builder vs Abstract Factory 패턴 

-> Abstract Factory 는 여러 군들에 관한 생성을 감춘다면 , Builder 는 하나의 군에 대한 생성하는 다양한 방식에 대한 정보를 감춘다.

8.  Abstract Factory vs Factory Method

->Gof 의 Factory Method 는 파생된 클래스가 오버라이딩한 메소드를 통해 객체를 생성하는 매우 간단한 의미를 가진다. 자바진영에서 사용되는 팩토리패턴과는 조금 다르다. 팩토리 패턴은 오버라이딩한 메소드를 통해 생성한다는 족쇄가 없다.  Abstarct Factory 는 종종 Factory Method 를 이용하여 (이용 안해도 됨) 여러군에 대한 생성을 유연하게 생성하는데 목적이 있다. 

9. Factory Method vs Templet Method 패턴 
->
 Factory Method 는 파생된 클래스가 오버라이딩한 메소드를 통해 객체를 생성하는 것을 의미하는 간단한 거라면, Template Method 는 부모클래스의 메소드를 통해 로직의 와꾸를 정하고, 그 로직에서 추상메소드를 호출하는 것이다. 파생된 클래스는 그 추상메소드의 상세 알고리즘을 구현하게 된다.

10. Iterator vs Visitor 패턴 

-> Visitor 는 노드에서 노드로 자신이 넘겨지는 반면, Iterator 는 하나의 노드 내부를 탐색하기 위함이다.

11. Visitor vs Strategy 패턴 

-> Visitor 는 노드에서 노드로 넘겨지면서 자신의 알고리즘이 수행되는 반면, Strategy 는 하나의 노드에서 특정 알고리즘을 선별하여 사용한다. 

12. Strategy  vs 

Chain of Responsibility 패턴 

-> , Strategy 는 하나의 노드에서 특정 알고리즘을 선별하여 사용하는 반면, Chain of Responsibility 는 하나의 메세지가 다양한 노드에 존재하는 알고리즘의 적용을 거치게 한다.

13. 

Chain of Responsibility

  vs 

Visitor 패턴 

-> Chain of Responsibility 는 하나의 메세지가 다양한 노드에 존재하는 알고리즘을 거치는 반면, Visitor 는 자신의 알고리즘이 노드에서 노드로 옮겨지면서 적용된다. 

13. Strategy vs State 패턴 

-> Strategy 는 다양한 알고리즘 중에 하나를 주입받아 사용하는것이고, State 는 상태별 행위를 외부에 정의해 놓고 , 자신의 상태에 따라서 외부에 정의한 행위를 수행한다. 

14. Flayweight vs Prototype 패턴

-> Flayweight 는 자기와 남이 (외부에서 주입을 받는 등등) 동일한 객체를 참조하는 것이고, Prototype은 이미 만들어진 객체의 복사본을 만드는것이다. 클래스가 틀이 되는게 아니라 이미 만들어진 객체가 틀이 된다. 따라서 이미 만들어진 객체와는 조금 다른 속성을 지는 clone 이 만들어 진다. DeepCopy 를 하든 ,ShallowCopy 를 하든 상관없다. 

15. Prototype vs Memento 패턴 

-> Prototype은 이미 만들어진 객체의 복사본을 만드는것이다. Memento 도 이미 존재하는 객체들의 사본을 만든다. 하지만 의도는 전혀 다르다. Prototype 이 클래스를 너무 많이 만들게 되는 우를 범할까봐, 하나의 클래스를 통한 다양한 객체를 만들어두고, 그 객체들의 Clone 을 만드는 것이라면, Memento 는 다시 돌려지기 위한 객체들의 상태를 기록 (보통 외부로) 해 두기 위함이다. 

16. 

Memento vs Command 패턴 

-> Memento 가 상태와 연산이 알려지지 않은 객체를 캡슐화하고 저장해 놓는게 목적인 반면에, Command 는 행위를 객체로 만드는것이 목적이며, 그 객체에는 상태와 연산이 존재하며, 사용자는 그것에 대해 잘 알고 있다. 왜냐하면 행위를 번복(Undo) 하려 할때, 상태를 되돌리고, 반대연산을 수행해 줘야 하기 때문이다.  둘다 Undo /Redo 에 많이 사용된다.

* 본 글은 생각나는데로 투박하게 써 내려갔으며, 저자의 주관이 많이 들어가 있음을 말해드립니다. 디자인 패턴은 패러다임,언어특성 마다 구현이 달라지나 의도는 일치해야합니다. 왜냐하면 패턴은 커뮤니케이션의 목적이 꽤나 강한데, "의도" 가 달라져 버리면 , 패턴을 정의하는 의미가 없어지기 때문입니다.따라서 본 글에서의 잘못된 "의도" 설명 or 추가 할 필요가 있는 부분이 있으면 언제라도 지적 부탁드립니다. 감사합니다.

* 자아비판좀 하자면 패턴에 대해서 꽉 잡고(?) 있더라도 바쁘다는 핑계하에 그냥 함수쪼개기/외부주입 정도만 신경 쓰고 더 신경 쓰기 귀찮아서 더 잘 할 수 있는것을 나중으로 미루고 있는 저보다는 패턴 같은거 잘 몰라도 코딩 할 때 마다 진지하게 장인정신을 발휘하는 사람이 훨씬 좋은 코드를 만드는게 사실일 겁니다.

Comments