Observer 패턴. 상태값에 변화가 생겼을때 옵저버들에게 알려주는 패턴이다.

Head First에서 예제로는,
기상청에서 날씨 정보가 변경되었을시에 몇가지 디스플레이에 날씨 정보를 갱신해주는..
혹은 출판사와 구독자의 관계를 옵저버 패턴으로 설명했다.

java.util.Observer;
java.util.Observable;

java.util에 Observer 인터페이스와 Observable 추상클래스가 존재하는데,
위에서 설명한 예로 보자면 출판사와 기상청은 Observable, 디스플레이와 구독자 같은 대상은 Observer가 된다.

저 두가지 클래스를 이용하면 쉽게 옵저버 패턴을 구현할 수 있다.
간단한 예의 Observable이다. 랜덤 숫자를 옵저버들에게 알려주는 일을 하고 있다.
이 Observer는 update메서드를 통해서 호출한 Observable객체와 상태값을 전달 받아서 랜덤숫자가 몇인지 확인한다.

간단한 옵저버 패턴의 예이긴하나 실제로 사용해본적이 없어서 장,단점은 정확하게 집어내기 힘들다.
그래도 단순하게 구지 꼽자면.. 일단 Observable은 Abstract 클래스이기 때문에 다중상속이 안된다.
또 Observer가 하나의 Observable에 속해있단 보장이 없다. 그러면 update에서 instanceof로 Observable을 골라내야 하는것인가..?

아마도 저런 해결책은 이미 존재할꺼라고 생각한다. 처음 접해보는 나같은 사람도 보이는데..;;
해결책에 대한건 내공이 좀 쌓이면 그때 고민해보도록 하자 -_-; 

'Design Patterns' 카테고리의 다른 글

Strategy.  (0) 2012.03.03
"OCP", Open Closed Principle  (0) 2012.02.26
"LSP", Liskov Substitution Principle  (2) 2012.02.26
"ISP", Interface Segrehation Principle  (1) 2012.02.26
"DIP", Dependency Inversion Principle  (0) 2012.02.26
"Strategy", 계획, 전략, 문제를 해결하기 위한 방법. '알고리즘'.
이 패턴은 알고리즘을 구현한 부분을 상황에 맞게 교체해서 같은 문제를 다른 방법으로 해결할수 있게 도와주는 패턴이다.

대부분 교육기관에서 가르치는 예제들은 아래와 같은 형태의 서비스 구조를 갖는다.

아래 코드에서의 strategy는 BoardDao로 보면 되겠다.

BoardServiceImpl은 BoardDao의 구현 클래스를 모르는 상태이고, BoardService가 해야할 regist, update, read 기능을 BoardDao에 위임했다.

생성자, 또는 setter메서드를 이용해서 상황에 맞게 jdbc, ibatis, hibernate를 사용할수 있는 전략을 가질수 있다.

나도 마찬가지지만, 교육기관에서 당연하듯이 저런식으로 코드를 쓰다보니 딱 저런 예제 말고 다른 로직(아파치, 오픈소스 등..)에서는 strategy패턴(등..)을 인지하지 못하고, 또 응용하지도 못한다.

어여 나도 소스를 볼줄 아는 눈을 가져야 하는데 큰일이다..;

'Design Patterns' 카테고리의 다른 글

Observer.  (0) 2012.03.17
"OCP", Open Closed Principle  (0) 2012.02.26
"LSP", Liskov Substitution Principle  (2) 2012.02.26
"ISP", Interface Segrehation Principle  (1) 2012.02.26
"DIP", Dependency Inversion Principle  (0) 2012.02.26
"개방 폐쇄 원칙"
"모듈은 확장에는 열려있어야 하고, 변경에는 닫혀있어야 한다."

책을 봐도 모르겠다..^^;; 이번주 한번 더 봐야할듯 하다. 죄송~ 

'Design Patterns' 카테고리의 다른 글

Observer.  (0) 2012.03.17
Strategy.  (0) 2012.03.03
"LSP", Liskov Substitution Principle  (2) 2012.02.26
"ISP", Interface Segrehation Principle  (1) 2012.02.26
"DIP", Dependency Inversion Principle  (0) 2012.02.26
"리스코프 대체 원칙"
"기반 클래스는 구현 클래스로 대체 가능해야 한다."

기반 클래스 - Map, List, Set 등..
구현(파생) 클래스 - HashMap, HashTable, ArrayList, CheckedList, HashSet 등..

역시나 책을 아무리 읽어봐도 이해하기가 어렵다. 내 맘대로 해석해본다.

아래와 같은 상황이 "기반 클래스가 구현 클래스를 대체하고 있는 것"이다. 라고 해석했다.

보통 저렇게 습관적으로 써와서 그런가 원칙 설명이 쉽게 이해가 되지 않는다.
책 예제에 있는 소스를 실행해보면,

지원하지 않는다고 예외가 떨어졌고 결국 기반 클래스인 List는 구현 클래스를 대체하지 못했다.

Arrays.asList()은 배열을 List타입으로 변환해준다. 소스를 보면 분명 new ArrayList(obj) 를 리턴하고 있지만 저 ArrayList는 Arrays클래스의 내부 클래스인 ArrayList이다.


그 ArrayList는 AbstractList를 상속받고 있지만 add() 메서드 기능을 재구현 하지 않았다. 그래서 AbstractList의 add() 메서드가 호출되면서 UnsupportedOperationException을 던지게 되어있다.

왜 저런식으로 한건지 모르겠다. 왜 AbstractList는 구현 클래스들이 add()를 구현하게끔 강제하지 않았는지..
저런식으로 Exception을 던져버리면 하위 클래스에서는 add() 메서드의 중요함은 모른채 동작되고 있을 것이다.

사실 List는 굉장히 많이 사용되고 있는 Interface이고 List의 add() 메서드는 거의 그림자 처럼 따라다니며 사용되는데 List를 상속받은 AbstractList부터 add() 메서드는 사용될 수도, 안될 수도 있게 되버렸다.

"자식(구현)은 부모(기반)의 유산(메서드) 중 일부를 거부하면 안된다."
거부하면 위와 같이 기반 클래스는 구현 클래스를 대체할 수 없게 된다. 라는 뜻으로 이해하려 한다.


5개 밖에 안되는 원칙을 보고 있는데 뒤죽박죽 헷갈린다. 나름대로 공부하고 정리할겸 포스팅을 하는건데 내용을 보면 모르는것 투성이라서 너무 창피하다..;; 어디서 무림 고수가 등장해서 리플하나 남겨주지 않으시려나..^^

'Design Patterns' 카테고리의 다른 글

Strategy.  (0) 2012.03.03
"OCP", Open Closed Principle  (0) 2012.02.26
"ISP", Interface Segrehation Principle  (1) 2012.02.26
"DIP", Dependency Inversion Principle  (0) 2012.02.26
"SRP", Single Responsibility Principle  (0) 2012.02.25
"인터페이스 분리의 원칙"
"클라이언트에 특화된 여러개의 인터페이스가 하나의 범용 인터페이스 보다 낫다."

책에 글씨로 된 설명은 그럭저럭 이해를 하겠는데 그림으로 표현한 클래스 관계도를 보면 이해하기 어렵다.

그냥 내 맘대로 해석해봤다. 예를 들어서 아래와 같은 게시판 CRUD 서비스가 있다고 가정한다.

관리자 게시판 기능은 위 서비스 모두 사용이 가능하지만 "일반 사용자는 게시글 삭제 기능이 없다." 라고 한다면..
이런 상황에서 인터페이스를 분리해야 하는것 같다. 그렇다면 이런식으로 분리하면 된단 얘기인가..

관리자는 이런식으로 인터페이스를 구현할 것이고..

일반 사용자는 이런식으로 인터페이스를 구현할 것이다.

아니면.. 인터페이스를 분리해서 한쪽이 상속받아야 하는것인가? 일단 인터페이스끼리의 상속..을해도 분리라고 해석했다.

이렇게 관리자 Interface를 새로 구성해서 관리자 클라이언트는 AdminBoardService에 의존하게 하는편이 맞는것 같다.
어차피 BoardService의 의미와 목적은 살아있고 LSP, DIP도 지켜지기 때문이다.

내 나름대로의 해석이라 확실하지 않다는점이 걸리긴 하다 &:D

'Design Patterns' 카테고리의 다른 글

"OCP", Open Closed Principle  (0) 2012.02.26
"LSP", Liskov Substitution Principle  (2) 2012.02.26
"DIP", Dependency Inversion Principle  (0) 2012.02.26
"SRP", Single Responsibility Principle  (0) 2012.02.25
High Cohesion, Low Coupling.  (0) 2012.02.25
"의존 관계 역전의 원칙"
"클라이언트는 구현 클래스가 아닌 인터페이스나 추상 클래스에 의존해야 한다."

구현 클래스는 인터페이스보다 변하기 쉽다. 구현 클래스에 의존한 클라이언트는 구현 클래스의 변경에 따라 클라이언트 역시 변경이 요구될 수 있다.

"ArrayList list = new ArrayList();"
구현 클래스에서 많이 사용되고 있는 메서드의 리턴 타입이 바뀌었다면,
그 구현 클래스의 메서드를 사용하고 있는 많은 부분들은 리턴 타입에 맞게 수정을 해야한다.

"List list = new ArrayList();"
하지만, 인터페이스를 구현하게 되면, 구현 클래스를 직접 의존할 필요없이 인터페이스에 의존하여 구현 클래스의 변화에 따른 충격을 피할 수 있다.


이 원칙을 따른다면, 모든 클래스는 최소 하나의 인터페이스를 가져야 한다. 이는 오히려 시스템의 복잡도를 증가시킨다.
DIP는 변화나 확장이 예측되는 부분에 적용해야 한다.
"단일 책임의 원칙"
"객체는 하나의 책임만을 맡아야 한다."

억지로 책임을 나누지 않는다. 책임은 변화의 축이며, 하나의 요구사항 변경은 하나의 책임을 변경하게 하는 경우가 많다.
책임의 범위가, 크기가 클수록 변경에 대한 영역도 그만큼 커지게 된다.

변화에 효율적으로 대응할수 있는 크기의 책임을 할당하는것이 좋다.


하나의 클래스가 여러 책임을 맡는것도 곤란하다.

클래스가 여러 원인에 의해 변경되기 때문..


하나의 책임을 여러 클래스로 분리하는것도 곤란하다.

하나의 원인으로 여러 클래스가 변경되기 때문..


확실하게 책임에 대한 구현을 은닉해 놓았다면 한 클래스에 두개의 책임이 혼재하더라도 변경으로 인한 여파를 최소화 할 수 있다.
높은 응집도 (High Cohesion),
낮은 결합도 (Low Coupling).

응집도란 '하나의 클래스가 하나의 기능을 담당하고 있는 정도'를 의미.
응집도가 높을수록 클래스와 프로그램의 구조는 단순해진다.

결합도란 '클래스간의 서로 다른 책임들이 얽혀있는(상호 의존) 정도'를 의미.
결합도가 높을수록 코드를 읽기 어려워진다.
서로 다른 책임이 복잡하게 얽혀있으면 가독성이 떨어지고 유지보수가 곤란하다.
즉, 하나의 클래스(책임) 변경이 얽혀있는 다른 클래스(책임)에 변경을 요구하는 일이 발생할 수 있다.

결합도가 0인 경우는 클래스 간에 아무런 연관 관계가 없다는 의미이다.

프로그램이 작동하기 위해서는 데이터를 주고 받을수 밖에 없다.
그러기 위해서 어느정도의 결합 관계는 필요하다.

+ Recent posts