天天看點

設計模式:觀察者模式 和 釋出-訂閱模式

一、簡介

觀察者模式是一種使用率很高的模式。這個模式的一個重要作用就是解耦,将被觀察者和觀察者解耦。在很多地方,都會将觀察者模式稱為釋出-訂閱模式,或者訂閱者模式。實際上,兩者是不完全相同的,有聯系也有差別。

二、觀察者模式定義

觀察者模式,定義了一種一對多的依賴關系,使得當一個對象發生狀态變化時,則觀察它的對象也都得到通知并作出反應。

三、UML類圖

設計模式:觀察者模式 和 釋出-訂閱模式
  • 抽象主題(Subject):它把所有觀察者對象的引用儲存到一個集合中,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以注冊和移除觀察者。
  • 具體主題(ConcreteSubject):将有關狀态存入具體觀察者對象;在具體主題内部狀态改變時,給所有登記過的觀察者發出通知。
  • 抽象觀察者(Observer):為所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
  • 具體觀察者(ConcreteObserver):實作抽象觀察者提供的更新接口,以便本身的狀态能夠及時更新。

四、觀察者模式的實作例子

1、建立一個抽象觀察者

public interface Observer {//抽象觀察者
        public void update(String message);//更新方法
    }
           

2、建立具體觀察者(以開學為例)

public class Student implements Observer {

        private String name;
        public Student (String name) {
            this.name = name;
        }
        @Override
        public void termBegins(String message) {
            System.out.println(message + "," + name+"背上書包去學校");
        }
    }

    public class Teacher implements Observer {

        private String name;
        public Teacher (String name) {
            this.name = name;
        }
        @Override
        public void termBegins(String message) {
            System.out.println(message + "," + name+"準備布置新學期學習任務");
        }
    }
           

3、建立抽象主題

public interface  Observable {
         void add(Observer observer);
 
         void remove(Observer observer);
    
         void notify(String message);
    }
           

4、建立具體主題

public class School implements  Observable{
        
        private List<Observer> personList = new ArrayList<Observer>();
        @Override
        public void add(Observer observer) {
            personList.add(observer);
        }

        @Override
        public void remove(Observer observer) {
            personList.remove(observer);

        }

        @Override
        public void notify(String message) {
            for (Observer observer : personList) {
                observer.termBegins(message);
            }
        }
    }
           

5、用戶端測試

public void test(){
        Observable school = new School();       
        Observer stu1=new Student("小明");
        Observer teacher1=new Teacher("王老師");

        school.add(stu1);
        school.add(teacher1);       
        school.notify("開學了!");
    }
           

五、釋出-訂閱模式

設計模式:觀察者模式 和 釋出-訂閱模式

聯系

釋出-訂閱模式是觀察者模式的一種變體。釋出-訂閱隻是把一部分功能抽象成一個獨立的“中間件”進行轉發控制。

差別

1、觀察者模式中主體和觀察者是互相感覺的,釋出-訂閱模式是借助第三方來實作排程的,釋出者和訂閱者之間互不感覺。

觀察者模式比較好了解,釋出訂閱模式舉個栗子,就像報社, 郵局和個人的關系,報紙的訂閱和分發是由郵局來完成的。報社隻負責将報紙發送給郵局。

2、觀察者模式是【一對多】的關系。一觸發通知,所有觀察者都收到消息。

釋出-訂閱模式是【多對一】或者【多對多】的關系。

釋出-訂閱模式适合更複雜的場景,比如隻想通知部分訂閱者,比如多個釋出者釋出消息時,通知時機的選擇(都釋出完再通知還是每釋出一個通知一次)。而這些控制的邏輯就是在“中間件”完成的。

六、釋出-訂閱模式例子

var publisher = {
	publish(pubsub) {
		pubsub.publish()
	}
}
var pubsub = {
	subscribes: [],
	publish() {
		this.subscribes.forEach(subscribe =>{
			subscribe.update();
		})
	},
	subscribe(sub) {
		this.subscribes.push(sub)
	}
}
var subscribe = {
	update() {
		console.log('update')
	},
        subscribe(pubsub) {
            pubsub.subscribe(this);
        }
}
subscribe.subscribe(pubsub)
publisher.publish(pubsub)
           

感謝-> https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/25

看代碼就很容易了解了。轉一下java實作也不難,這裡就偷個懶了~

繼續閱讀