티스토리 뷰
출처 링크: https://www.youtube.com/watch?v=_BpmfnqjgzQ
관련 도서: http://www.yes24.com/Product/Goods/1778966
Head First Design Patterns - YES24
정말 쿨~ 하게 배우는 디자인 패턴 학습법다른 사람들이 뭔가를 만들어 놓았고, 누구든 마음대로 사용해도 되는 게 있다면 굳이 고생해서 똑같은 걸 만들어 써야 할 필요는 없을 것이다. 소프트
www.yes24.com
아래 내용은 제 100% 주관적인 내용입니다. 아래 내용이 잘못 되어도 어떠한 책임도 지지 않겠습니다.
비판적으로 내용을 받아들여주세요.
디자인 패턴 UML
UML을 보면 꽤 복잡해 보인다.
하지만 사실 복잡하지 않다. 천천히 뜯어 보어보자.
우선 위 그림에서 아래 그림1, 그림2 처럼 나눠서 봐야한다.
그림1과 그림2는 단지 아래 그림처럼 나눈것 뿐이다.
그림 1의 UML은 NewMachine에서 어떠한 변경이 있어서 notify를 실행하면 Observer의 구현체(EventSubscriber)는 변경을 감지할 수있다. 하지만 어떠한 내용이 바뀌었는지 알 수 없다. 단지 감지만 할 뿐이다.
반면에 그림 2의 UML은 notify를 실행하면 Observer의 구현체(AnnualSubscriber)는 변경을 감지한다. 그리고 Publish의 구현체(NewsMachine)을 가지고 있으므로 변경된 내용을 알 수 있다.
이 둘의 차이를 구분하지 않고 책에서 하나만 소개하는 경우가 많은지 그림 2번에 대한 질문이 스택오버플로우에 자주 올라온다고 한다. 질문 내용 대부분이 "디자인 패턴은 설계를 추상화하는데 의미가 있는데.. 왜 구현체단(NewsMachine, AnnualSubscriber)에서 컴포지션 관계가 있나요?"
이유는 변경 내용을 알기 위해서이다. 위의 UML들에서는 AnuualSubscriber가 getTitle()과 getNews()를 통해서 필요한 정보를 얻을 수 있을 것이다.
따라서 상황에 맞게 감지만 필요한지 아니면 감지하고 어떤 내용이 변경되었는지도 알아야 하는지에 따라 선택하면 된다.
디자인 패턴 Sample Code
public interface Observer {
public void update(String title, String news);
}
public interface Publisher {
public void add(Observer observer);
public void delete(Observer observer);
public void notifyObserver();
}
public class NewsMachine implements Publisher {
private ArrayList < Observer > observers;
private String title;
private String news;
public NewsMachine() {
observers = new ArrayList < > ();
}
@Override public void add(Observer observer) {
observers.add(observer);
}
@Override public void delete(Observer observer) {
int index = observers.indexOf(observer);
observers.remove(index);
}
@Override public void notifyObserver() {
for (Observer observer: observers) {
observer.update(title, news);
}
}
public void setNewsInfo(String title, String news) {
this.title = title;
this.news = news;
notifyObserver();
}
public String getTitle() {
return title;
}
public String getNews() {
return news;
}
}
public class AnnualSubscriber implements Observer {
private String newsString;
private Publisher publisher;
public AnnualSubscriber(Publisher publisher) {
this.publisher = publisher;
publisher.add(this);
}
@Override public void update(String title, String news) {
this.newsString = title + " \n -------- \n " + news;
display();
}
private void display() {
System.out.println("\n\n오늘의 뉴스\n============================\n\n" + newsString);
}
}
public class EventSubscriber implements Observer {
private String newsString;
private Publisher publisher;
public EventSubscriber(Publisher publisher) {
this.publisher = publisher;
publisher.add(this);
}
@Override public void update(String title, String news) {
newsString = title + "\n------------------------------------\n" + news;
display();
}
public void display() {
System.out.println("\n\n=== 이벤트 유저 ===");
System.out.println("\n\n" + newsString);
}
}
public class EventSubscriber implements Observer {
private String newsString;
private Publisher publisher;
public EventSubscriber(Publisher publisher) {
this.publisher = publisher;
publisher.add(this);
}
@Override public void update(String title, String news) {
newsString = title + "\n------------------------------------\n" + news;
display();
}
public void display() {
System.out.println("\n\n=== 이벤트 유저 ===");
System.out.println("\n\n" + newsString);
}
}
내가 느낀 이 패턴의 특징
구조는 스트래티지 패턴과도 비슷하다.
하지만 큰 차이점은 메시지를 받게되는 지점에서 메시지를 보낸 쪽의 정보를 알고 싶어하는지 여부일 것 같다.
모든 Observer패턴이 항상 그런건 아니지만 위의 그림 1은 Observer 패턴이라고 할 수 있지만 동시에 스트래티지 패턴이라고도 할 수 있다. 하지만 그림 2에서처럼 Observer 인터페이스의 구현체들에서 Publiser의 정보를 가져갈 수 있도록 함으로써 정보를 다른 곳으로 옮길 수 있게한다.
(여기에서는 notify를 통해서 Observer의 update()를 호출하여 메시지를 받는다. 스트래티지 패턴도 역할을 위임받은 곳으로 메소드가 호출되는 방향과 구조가 똑같다.)
어떨 때 이 패턴을 사용하면 좋을까?
1 : N 관계이고 역할을 위임받을 쪽에서 정보를 알아야 할 때!
'개발 > 디자인패턴' 카테고리의 다른 글
데코레이터 패턴 - 디자인 패턴 [ep 3] (0) | 2021.10.10 |
---|---|
스트래티지 패턴 - 디자인 패턴 [ep 1] (0) | 2021.09.30 |
브릿지 패턴 - 디자인 패턴 [ep 11] (0) | 2021.09.26 |