設計模式:5.觀察者模式(發佈訂閱)

觀察者模式

觀察者模式屬於行爲型模式,又叫發佈訂閱模式

定義:

​ 定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新

模式類圖
在這裏插入圖片描述
角色:

  1. 被觀察者:Subject定義一個被觀察者必須實現職責,包括動態增加,刪除,通知觀察者
  2. 觀察者:Observer接受到觀察者修改消息,執行自身邏輯
  3. 具體觀察者:ConctreteSubject繼承Subject,擁有自己的業務邏輯,具有被觀察者基本功能,對某些事件進行通知
  4. 具體的觀察者:ConcreteObserver具體觀察者,在接受到被觀察者變更消息後,進行各自業務處理

優點

  1. 觀察者和被觀察者之間是抽象耦合,容易拓展

  2. 通過觸發機制可以創建成一種鏈式觸發機制,形成多級觸發

    缺點

  3. 執行效率
    當通知觀察者是順序執行時,需要考慮整個觀察者列表的數量,對整個通知事件執行效率的影響,可以考慮使用異步通知,同時儘量避免多級觸發事件

  4. 循環依賴
    當觀察者和被觀察之間形成循環依賴,會導致循環調用,比如A改變通知B,B改變通知C,C改變通知A,注意避免循環依賴的發生

被觀察者接口
Subjectable 定義被觀察者基本功能

public interface Subjectable {

    /**
     * 增加觀察者
     */
    void addObserver(Observerable observer);

    /**
     * 移除觀察者
     */
    void removeObserver(Observerable observer);

    /**
     * 通知觀察者
     */
    void notifyObserver(Object object);
}

被觀察者抽象類
AbstractSubject被觀察者類的公共父類,實現了被觀察者基本功能的實現,使用Vector爲觀察者列表

public abstract class AbstractSubject implements Subjectable{

    /**
     * 觀察者列表
     */
    private Vector<Observerable> observers = new Vector();

    @Override
    public void addObserver(Observerable observer){
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observerable observer){
        observers.add(observer);
    }

    @Override
    public void notifyObserver(Object object){
        observers.forEach(observer->{
            observer.update(object);
        });
    }
}

被觀察者類
UserInfo實現AbstractSubject

@Data
public class UserInfo extends AbstractSubject{

    /**
     * 暱稱
     */
    private String nickName;
    /**
     * 密碼
     */
    private String password;

    /**
     * 修改密碼
     * @param password
     */
    public void updatePassword(String password){
        this.password = password;
        this.notifyObserver(password);
    }

    public UserInfo(String nickName, String password) {
        this.nickName = nickName;
        this.password = password;
    }
}

觀察者接口

public interface Observerable {

    /**
     * 被觀察者變化觸發事件
     */
    void update(Object object);
}

具體觀察者
SmsObserver 接收到被觀察者密碼變更,發送短信提醒

public class SmsObserver implements Observerable {

    @Override
    public void update(Object object) {
        if(null == object){
            return;
        }
        System.out.println("短信觀察者");
        System.out.println("短信發送提醒:密碼更改爲:"+object.toString());
    }
}

EmailObserver 接收到被觀察者密碼變更,發送郵件提醒

public class EmailObserver implements Observerable{

    @Override
    public void update(Object object) {
        if(null == object){
            return;
        }
        System.out.println("郵件觀察者");
        System.out.println("郵件發送提醒:密碼更改爲:"+object.toString());
    }
}

驗證

public static void main(String[] args) {

    UserInfo userInfo = new UserInfo("麻辣香鍋","malaxiangguo");

    SmsObserver smsObserver = new SmsObserver();
    EmailObserver emailObserver = new EmailObserver();

    userInfo.addObserver(smsObserver);
    userInfo.addObserver(emailObserver);

    userInfo.updatePassword("mlxg");
}

輸出

短信觀察者
短信發送提醒:密碼更改爲:mlxg
郵件觀察者
郵件發送提醒:密碼更改爲:mlxg

SmsObserver和EmailObserver觀察到UserInfo用戶麻辣香鍋更改密碼爲mlxg

參考:設計模式之禪:https://www.kancloud.cn/sstd521/design/193589

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