設計模式入門:觀察者模式

原文地址:http://te-amo.site/user/article/info/ARTICLE20180407063327367
文章中部分定義和解釋性文字,都是引用百度百科,主要的代碼及場景應用爲本人原創

一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知

場景:我在設計我個人網站時,有一個留言功能。其中有一個需求是:當管理員在後臺回覆留言後,要做三件事(1)更改數據庫,將處理完的留言標記爲已處理(2)將答覆內容通過郵件發送給留言人(3)給管理員一個提示告訴他,郵件已經發出。

其實面對這個場景,完全可以使用順序的方式來完成這一系列操作,先更新數據庫,再發送郵件,最後給管理員消息提示。但是這種設計不容易拓展與維護,如果以後需要增加新的操作,是需要修改整個邏輯結構。鑑於這個三個操作沒有嚴格的關聯要求,所以可以使用觀察者模式。

設計
這裏寫圖片描述

構成

  • 抽象觀察者角色:爲所有的具體觀察者定義一個接口,在得到主題通知時更新自己。(Observer)
  • 具體被觀察者角色:也就是一個具體的主題,在集體主題的內部狀態改變時,所有登記過的觀察者發出通知。(LeaveMessageSubject)
  • 具體觀察者角色:實現抽象觀察者角色所需要的更新接口,一邊使本身的狀態與製圖的狀態相協調。(ChangeDB,NotifyMessage,ReplyEmail)

實現

代碼地址:https://github.com/telundusiji/designpattern

Observer 抽象觀察者

public interface Observer {
    void update(Message message);
}

ChangeDB 具體觀察者,更新數據庫

@Slf4j
public class ChangeDB implements Observer {
    public void update(Message message) {
        log.info("留言:{},{},{},在數據庫中更新!",message.id,message.name,message.content);
    }
}

NotifyMessage 具體觀察者 給管理員進行消息提示

@Slf4j
public class NotifyMessage implements Observer{
    public void update(Message message) {
        log.info("留言:{},{},{},已通過郵件回覆",message.id,message.name,message.content);
    }
}

ReplyEmail 具體觀察者 發送郵件

@Slf4j
public class ReplyEmail implements Observer {
    public void update(Message message) {
        log.info("留言:{},{},{},發送郵件...",message.id,message.name,message.content);
    }
}

LeaveMessageSubject 具體被觀察者 message更新時通知所有觀察者

public class LeaveMessageSubject {
    List<Observer> observers;
    private Message message;
    public LeaveMessageSubject() {
        observers = new ArrayList<Observer>();
    }

    public void addObserver(Observer observer){
        observers.add(observer);
    }

    public boolean removeObserver(Observer observer){
        return observers.remove(observer);
    }

    public void notifyObserver(){
        for(Observer o : observers){
            o.update(message);
        }
    }

    public void setMessage(Message message) {
        this.message = message;
        notifyObserver();
    }
}

Message 留言實體

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Message {
    int id;
    String name;
    String email;
    String content;
}

經典應用

在servlet中Listener就是使用觀察者模式

  • EventListener 抽象的觀察者
  • ServletContextAttributeListener,ServletRequestAttributeListener…都是具體觀察者
  • HttpServletRequest…可以認爲是具體被觀察者

例如:當HttpServletRequest 調用setAttribute方法時,就會去調用notifyAttributeAssigned方法,此方法會創建對應的事件對象,然後通知所有觀察改事件的觀察則進行更新

具體細節可以去看源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章