DesignPattern - Behavioral - Observer
Tue, Aug 7, 2018
閱讀時間 2 分鐘
Observer (pub-sub)
在觀察者設計模式中,多個觀察者對象向一個主題註冊以獲取通知中的任何更改。當主題的狀態發生變化時,它會通知觀察者。監聽或觀察變化的對象稱為觀察者,被觀察的對象稱為主體。
主題為觀察者提供了一個接口,可以在主題中註冊和註銷自己。 主題知道它的訂閱者是誰。 多個觀察者可以訂閱通知。 主題發布通知。 主題只是發送通知說狀態已更改。它不傳遞任何狀態信息。 一旦收到來自主題的通知,觀察者就會調用主題並獲取更改的數據。
- Subject, 註冊觀察者。對象使用此接口註冊為觀察者,也可以將自己從觀察者中移除。
- Observer為對象定義了一個更新接口,這些接口應該被通知主題的變化。但是,所有的觀察者都需要實現 Observer 接口。該接口有一個方法 update(),當 Subject 的狀態發生變化時會調用該方法。
- ConcreteSubject,將感興趣的狀態存儲到 ConcreteObserver 對象。當它的狀態改變時,它會向它的觀察者發送一個通知。此外,一個具體的主題總是實現主題接口。我們使用 * notifyObservers() 方法在狀態發生變化時更新所有當前的觀察者。
- ConcreateObserver 維護對 ConcreteSubject 對象的引用並實現 Observer 接口。每個觀察者註冊一個具體的主題以接收更新。
public interface Subject {
public void registerObserver(Observer observer);
public void notifyObserver();
public void unregisterObserver(Observer observer);
public Object getUpdate();
}
public interface Observer {
public void update();
public void setSubject(Subject sub);
}
//Concrete Subject
public class Blog implements Subject {
List<Observer> observersList;
private boolean stateChange;
public Blog() {
this.observersList = new ArrayList();
stateChange = false;
}
@Override
public void registerObserver(Observer observer) {
observersList.add(observer);
}
@Override
public void notifyObserver() {
if (stateChange) {
for(Observer observer : observersList) {
observer.update();
System.out.println("Observer notified !");
}
}
}
@Override
public void unregisterObserver(Observer observer) {
observersList.remove(observer);
}
@Override
public Object getUpdate() {
Object changedState = null;
// should have logic to send the state change to querying observer
if (stateChange) {
changedState = "Observer Design Pattern";
}
return changedState;
}
public void postNewArticle() {
stateChange = true;
notifyObserver();
}
}
//Concrete Observer
public class User implements Observer {
private String article;
private Subject blog;
@Override
public void update() {
System.out.println("State change reported by Subject.");
article = (String) blog.getUpdate();
}
@Override
public void setSubject(Subject blog) {
this.blog = blog;
article = "No New Article!";
}
public String getArticle() {
return article;
}
}
public static void main(String[] args) {
Blog blog = new Blog();
User user1 = new User();
User user2 = new User();
blog.registerObserver(user1);
blog.registerObserver(user2);
user1.setSubject(blog);
user2.setSubject(blog);
System.out.println(user1.getArticle());
blog.postNewArticle();
System.out.println(user1.getArticle());
}
- 當一個抽像有兩個方面時,一個依賴於另一個。將這些方面封裝在單獨的對像中可以讓您獨立地改變和重用它們。
- 當對一個對象的更改需要更改其他對象時,您不知道需要更改多少個對象?
- 當一個對象應該能夠通知其他對象而不假設這些對像是誰。換句話說,您不希望這些對象緊密耦合。
reference: https://javatechonline.com/behavioral-design-patterns-in-java/#Template_Method_Design_Pattern