觀察者模式

 

 

 

前提:
在翻閱資料的時候,有人把觀察者(Observer)模式等同於發佈(Publish)/訂閱(Subscribe)模式,也有人認爲這兩種模式仍是存在差別,而我認爲確實是存在差別的,本質上的區別是調度的地方不一樣。可是由於後者是前者發展變異而來,故而列到一篇博客中html

觀察者模式
比較概念的解釋是,目標和觀察者是基類,目標提供維護觀察者的一系列方法,觀察者提供更新接口。具體觀察者和具體目標繼承各自的基類,而後具體觀察者把本身註冊到具體目標裏,在具體目標發生變化時候,調度觀察者的更新方法。前端

由於前端語言紛繁複雜,下邊我分別舉出es五、es六、ts版本java

 

ts版本程序員

/***
 * 抽象被觀察者接口
 * 聲明瞭添加、刪除、通知觀察者方法
 */
public interface Observerable {
    registerObserver(o:Observer);
    removeObserver(o:Observer):;
    notifyObserver();
}

/***
 * 抽象觀察者
 * 定義了一個update()方法,當被觀察者調用notifyObservers()方法時,觀察者的update()方法會被回調。
 */
public interface Observer {
    update( message:string);
}



/**
 * 被觀察者,也就是微信公衆號服務
 * 實現了Observerable接口,對Observerable接口的三個方法進行了具體實現
 */
public class WechatServer implements Observerable {
    private list:Observer[];
    private message:string;
    constructor(){
        this.list = [];
    }
    public registerObserver(o: Observer) {
        this.list.push(o)
    }
    public removeObserver(o: Observer) {
        for (var i=0; i < this.list.length; i++){
            if (this.list[i] === o){
                this.list.splice(i, 1);
                break;
            }
        }
    }
    public notifyObserver() {
        for(let i = 0; i < this.list.length; i++) {
            let oserver = this.list[i];
            oserver.update(this.message);
        }
    }
    public setInfomation(s:string) {
        this.message = s;
        console.log(`微信服務更新消息:${s}`);
        //消息更新,通知全部觀察者
        this.notifyObserver();
    }
}


/**
 * 觀察者
 */
public class User implements Observer {
    private  name:string;
    private  message:string;
    constructor(name:string) {
        this.name = name;
    }
    public update(message:string) {
        this.message = message;
        this.read();
    }
    public read() {
        console.log(`${this.name}收到推送消息:${this.message}`);
    }
}


/**
 * 咱們來測試
 */
let server = new WechatServer();
let userZhang = new User("張三");
let userLi = new User("李四");
let userWang = new User("王五");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的語言!");
console.log("-----用戶張三看到消息後頗爲震驚,果斷取消訂閱,這時公衆號又推送了一條消息,此時用戶ZhangSan已經收不到消息,其餘用戶仍是正常能收到推送消息----------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的語言!");



/**
 * 總結:這個是ts去寫的,由於用js寫,我以爲理解起來很費勁,哪怕是es2018!編譯後可能就是你想要的版本吧
 * 這個模式是典型的觀察者模式,而非變異後的發佈-訂閱模式,二者有關聯,可是並不同
 * 其實前邊兩個接口是能夠不用定義的,可是接口就是用來作規範的,之後可能不僅有微信服務,還有新聞訂閱、小程序訂閱、iphoneXR訂購等等
 * 這個模式是鬆偶合的。改變主題或觀察者中的一方,另外一方不會受到影像
 * 參考自java設計模式:https://www.cnblogs.com/luohanguo/p/7825656.html
 */
View Code

 

es5版本
寫完以後,忽然發現,這尼瑪不就是ts編譯後的代碼嘛,那兩個抽象類的做用僅僅用在編譯階段,編譯後的代碼並不存在相關接口代碼,哦!原來ts是這麼個機制es6

/**
 * 被觀察者,也就是微信公衆號服務
 */
var WechatServer = (function () {
    function WechatServer() {
        this.list = [];
    }
    WechatServer.prototype.registerObserver = function (o) {
        this.list.push(o);
    };
    WechatServer.prototype.removeObserver = function (o) {
        for (var i = 0; i < this.list.length; i++) {
            if (this.list[i] === o) {
                this.list.splice(i, 1);
                break;
            }
        }
    };
    WechatServer.prototype.notifyObserver = function () {
        for (var i = 0; i < this.list.length; i++) {
            var oserver = this.list[i];
            oserver.update(this.message);
        }
    };
    WechatServer.prototype.setInfomation = function (s) {
        this.message = s;
        console.log(`微信服務更新消息:${s}`);
        //消息更新,通知全部觀察者
        this.notifyObserver();
    };
    return WechatServer;
}());


/**
 * 觀察者
 */
var User = (function () {
    function User(name) {
        this.name = name;
    }
    User.prototype.update = function (message) {
        this.message = message;
        this.read();
    };
    User.prototype.read = function () {
        console.log(`${this.name}收到推送消息:${this.message}`);
    };
    return User;
}());



/**
 * 咱們來測試
 */
let server = new WechatServer();
let userZhang = new User("張三");
let userLi = new User("李四");
let userWang = new User("王五");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的語言!");
console.log("-----用戶張三看到消息後頗爲震驚,果斷取消訂閱,這時公衆號又推送了一條消息,此時用戶ZhangSan已經收不到消息,其餘用戶仍是正常能收到推送消息----------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的語言!");
View Code

 

es6版本
經過這個能夠了解到,由於目前包括es2018還沒有實現接口、抽象功能,故而沒法定義觀察者約束性接口,而後還知道了,es6只是語法糖,相似於ts同樣,建立類,其實本質就是es5 混合繼承知識點:屬性用構造,公共函數放在原型對象上,這樣全部實例在內存共享一個方法,節省內存,說遠了,哈哈不說了,貼代碼面試

/**
 * 被觀察者,也就是微信公衆號服務
 */
class WechatServer{
    constructor(){
        this.list = [];
    }
    registerObserver(o) {
        this.list.push(o);
    };
    removeObserver(o){
        for (var i = 0; i < this.list.length; i++) {
            if (this.list[i] === o) {
                this.list.splice(i, 1);
                break;
            }
        }
    }
    notifyObserver() {
        for (var i = 0; i < this.list.length; i++) {
            var oserver = this.list[i];
            oserver.update(this.message);
        }
    }
    setInfomation(s){
        this.message = s;
        console.log(`微信服務更新消息:${s}`);
        //消息更新,通知全部觀察者
        this.notifyObserver();
    }
}

/**
 * 觀察者
 */
class User{
    constructor(name) {
        this.name = name;
    }
    update(message) {
        this.message = message;
        this.read();
    };
    read (){
        console.log(`${this.name}收到推送消息:${this.message}`);
    };
};

/**
 * 咱們來測試
 */
let server = new WechatServer();
let userZhang = new User("張三");
let userLi = new User("李四");
let userWang = new User("王五");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的語言!");
console.log("-----用戶張三看到消息後頗爲震驚,果斷取消訂閱,這時公衆號又推送了一條消息,此時用戶ZhangSan已經收不到消息,其餘用戶仍是正常能收到推送消息----------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的語言!");
View Code

最後再想嗶嗶兩句:
ts和es6都是語法糖,因此面試的人會問你編譯以後會是啥樣,挺操dan的,由於java歷來不會問我編譯後的字節碼是什麼樣
ts跟es6比,就拿這個來講,可使用接口來約束觀察者,防止程序員亂寫,能夠用數據類型來約束各類參數和返回值,防止亂傳,等到了運行再報錯,代碼我都寫了幾千行了,誰tm找獲得啊。大致來講ts語法約束性較強,是強數據類型語言了,不少錯編譯階段就會報錯!小程序


 

相關文章
相關標籤/搜索