2023. 3. 6. 19:02ㆍcs일지
2023/03/06
- 학습내용
1.1 디자인 패턴이란?
sw디자인 패턴은 특정 문맥에서 공통적으로 발생하는 문제에 대해 재사용 가능한 해결책이다.
프로그래머가 어플리케이션이나 시스템을 디자인할 때 공통된 문제들을 해결하는데 쓰이는 형식화된 가장 좋은 관행이다.
소스나 기계 코드로 바로 전환할 수 있는 완성된 디자인은 아니며, 다른 상황에 맞게 사용할 수 있는 문제들을 해결하는데 쓰이는 서술이나 템플릿이다.
1) 옵저버 패턴(Observer Pattern)
옵저버 패턴은 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다
메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 패턴입니다.
주체란 객체의 상태 변화를 보고 있는 관찰자입니다.
옵저버란 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 '추가 변화 사항' 이 생기는 객체들을 의미합니다.
※ 폴링(Polling) 방식과 인터럽트(interrupt) 방식
이벤트를 감지하는 즉, 상태변화를 감지하는 방식은 폴링(Polling)방식, 인터럽트(interrupt) 방식 두가지가 있다.
여기서 옵저버 패턴이 인터럽트(interrupt) 방식으로 관리할 수 있도록 제시하는 패턴이다.
옵저버 패턴을 사용하지 않으면 폴링(Polling) 방식을 사용해야 한다.
폴링(Polling) 방식은 어떤 요구하는 상태가 되었는지를 주기적으로 감지하는 방식이다.
즉 CPU는 일정시간마다 주기적으로 데이터를 가진 주체의 상태를 체크하여 행위를 수행한다.
ex) SMS를 보내는 메시지 스케줄러는 30초마다 보내야할 메시지가 존재하는지를 관리 Model로부터 확인하며,
메시지가 존재하면 일괄적으로 보낸다.
하지만, 이 방식은 CPU가 이벤트 감지에 대해서 주기적으로 체크해야하는 비용이 존재하며 어떤 이벤트가 발생했을 때 즉시 대응을 할 수가 없다.
그렇지만 인터럽트(interrupt) 방식을 사용하는 옵저버 패턴은 관찰자가 수동적으로 통보만 받는 방식이다.
주체는 어떤 상태가 되었을 때 관찰자들에게 상태 변화를 통보하며, 관찰자들은 받은 통보에 따라 어떤 행위를 수행한다.
이 방식은 CPU가 이벤트를 감시해야하는 비용이 없으며, 어떤 변화에 대해서 즉시 대응도 가능하다.
비용과 즉시 대응면을 생각한다면 인터럽트(interrupt) 방식을 사용하는 옵저버 패턴을 사용해야 한다.
옵저버 패턴은 객체와 주체가 분리되어 있는 패턴(1번)과
주체와 객체를 따로 두지 않고 상태가 변경되는 객체를 기반(2번)으로 구축되기도 한다.
옵저버 패턴의 ex) 트위터
내가 어떤 사람인 주체를 팔로우 했다면 주체가 포스팅을 올리게 되면 알림이 팔로워에게 간다.
옵저버 패턴은 주로 이벤트 기반 시스템에 사용하며 MVC 패턴에도 사용된다.
예를 들어 주체라고 볼 수 있는 모델에서 변경 사항이 생겨 update() 메서드로 옵저버인 뷰를 알려주고 이를 기반으로 컨트롤러 등이 작동하는 것이다.
여기서 view가 옵저버 역할을 하는 것이다.
JAVA 옵저버 패턴 구현
//JAVA 옵저버 패턴 구현
import java.util.ArrayList;
import java.util.List;
interface Subject {
public void register(Observer obj);
public void unregister(Observer obj);
public void notifyObservers();
public Object getUpdate(Observer obj);
}
interface Observer {
public void update();
}
class Topic implements Subject {
private List<Observer> observers;
private String message;
public Topic() {
this.observers = new ArrayList<>();
this.message = "";
}
@Override
public void register(Observer obj) {
if (!observers.contains(obj)) observers.add(obj);
}
@Override
public void unregister(Observer obj) {
observers.remove(obj);
}
@Override
public void notifyObservers() {
this.observers.forEach(Observer::update);
}
@Override
public Object getUpdate(Observer obj) {
return this.message;
}
public void postMessage(String msg) {
System.out.println("Message sended to Topic: " + msg);
this.message = msg;
notifyObservers();
}
}
class TopicSubscriber implements Observer {
private String name;
private Subject topic;
public TopicSubscriber(String name, Subject topic) {
this.name = name;
this.topic = topic;
}
@Override
public void update() {
String msg = (String) topic.getUpdate(this);
System.out.println(name + ":: got message >> " + msg);
}
}
public class HelloWorld {
public static void main(String[] args) {
Topic topic = new Topic();
Observer a = new TopicSubscriber("a", topic);
Observer b = new TopicSubscriber("b", topic);
Observer c = new TopicSubscriber("c", topic);
topic.register(a);
topic.register(b);
topic.register(c);
topic.postMessage("amumu is op champion!!");
}
}
/*
Message sended to Topic: amumu is op champion!!
a:: got message >> amumu is op champion!!
b:: got message >> amumu is op champion!!
c:: got message >> amumu is op champion!!
*/
코드 리뷰
Topic을 기반으로 옵저버 패턴을 구현했다.
Topic은 주체이자 객체가 된다.
class Topic implements Subject를 통해 Subject interface를 구현했고
Observer a = new TopicSubscriber("a", topic);으로 옵저버를 선언할 때 해당 이름과 어떠한 토픽의 옵저버가 될 것인지를 정했다.
참고자료
-면접을 위한 CS 전공지식 노트
'cs일지' 카테고리의 다른 글
cs 전공지식 #38 이터레이터 패턴 (0) | 2023.03.09 |
---|---|
cs 전공지식 #37 프록시 패턴과 프록시 서버 (0) | 2023.03.07 |
cs 전공지식 #35 전략 패턴 (0) | 2023.02.25 |
cs 전공지식 #34 팩토리 패턴 (0) | 2023.02.22 |
cs 전공지식 #33 운영체제 - CPU스케줄링 알고리즘 (0) | 2022.12.16 |