設(shè)計模式系列之觀察者模式
本文轉(zhuǎn)載自微信公眾號「狼王編程」,作者狼王 。轉(zhuǎn)載本文請聯(lián)系狼王編程公眾號。
大家好,我是狼王,一個愛打球的程序員
這篇讓我們來認(rèn)識一下觀察者模式
1、概述
觀察者模式是一種行為設(shè)計模式, 允許你定義一種訂閱機制, 可在對象事件發(fā)生時通知多個 “觀察” 該對象的其他對象。
2、適用場景
1)當(dāng)一個對象狀態(tài)的改變需要改變其他對象, 或?qū)嶋H對象是事先未知的或動態(tài)變化時, 可使用觀察者模式。
2) 當(dāng)應(yīng)用中的一些對象必須觀察其他對象時,可使用該模式。但僅能在有限時間內(nèi)或特定情況下使用。訂閱者可隨時加入或離開該列表。
3、實例
有以下場景:
- 有一個小區(qū),需要進(jìn)行核酸檢測。
- 假設(shè)每個人通過關(guān)注公眾號獲取核酸檢測結(jié)果。
發(fā)布者接口:
- /**
- * 發(fā)布接口
- */
- public interface IPublisher {
- /**
- * 發(fā)布事件
- * @param event
- */
- void publish(IEvent event);
- }
訂閱者接口:
- /**
- * 通用訂閱接口
- */
- public interface ISubscriber {
- /**
- * 查看結(jié)果
- */
- void look();
- }
事件接口:
- /**
- * 通用事件接口
- */
- public interface IEvent {
- /**
- * 打印事件信息
- */
- void print();
- }
消息發(fā)送者
- /**
- * 消息發(fā)送者
- */
- public class Publisher implements IPublisher{
- private IEvent event;
- private List<ISubscriber> subscribers;
- public Publisher(IEvent event, List<ISubscriber> subscribers) {
- this.event = event;
- this.subscribers = subscribers;
- }
- /**
- * 發(fā)布消息
- * @param event
- */
- @Override
- public void publish(IEvent event){
- event.print();
- }
- public IEvent getEvent() {
- return event;
- }
- public void setEvent(IEvent event) {
- this.event = event;
- }
- public List<ISubscriber> getSubscribers() {
- return subscribers;
- }
- public void setSubscribers(List<ISubscriber> subscribers) {
- this.subscribers = subscribers;
- }
- }
事件:
- /**
- * 檢測事件
- */
- public class CheckEvent implements IEvent{
- private String name;
- private String result;
- private ISubscriber subscriber;
- public ISubscriber getSubscriber() {
- return subscriber;
- }
- public void setSubscriber(ISubscriber subscriber) {
- this.subscriber = subscriber;
- }
- public CheckEvent(String name) {
- this.name = name;
- }
- @Override
- public void print() {
- subscriber.look();
- System.out.println("事件名稱:" + name);
- System.out.println("事件結(jié)果:" + result);
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getResult() {
- return result;
- }
- public void setResult(String result) {
- this.result = result;
- }
- }
訂閱者:
- /**
- * 訂閱者
- */
- public class User implements ISubscriber{
- private String name;
- public User(String name) {
- this.name = name;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public void look() {
- System.out.println("檢測姓名:" + name);
- }
- }
客戶端:
- /**
- * 測試類
- */
- public class TestDemo {
- public static void main(String[] args) {
- //定義兩種結(jié)果
- String[] doc = {"陰性", "陽性"};
- //初始化檢測事件
- CheckEvent check = new CheckEvent("核酸檢測");
- //初始化消息發(fā)布者
- Publisher publisher = new Publisher(check,new ArrayList<>());
- //實例化接受檢測的用戶
- List<ISubscriber> users = new ArrayList<>();
- for (int i = 0; i < 10; i++) {
- //初始化用戶
- User user = new User("狼王" + i);
- users.add(user);
- }
- //用戶訂閱事件
- publisher.setSubscribers(users);
- int index;
- //發(fā)布檢測結(jié)果
- for (int i = 0; i < 10; i++) {
- System.out.println("---------------");
- //隨機檢測結(jié)果
- index = (int) (Math.random() * doc.length);
- check.setSubscriber(users.get(i));
- check.setResult(doc[index]);
- //發(fā)布
- publisher.publish(check);
- }
- }
- }
結(jié)果:
- ---------------
- 檢測姓名:狼王0
- 事件名稱:核酸檢測
- 事件結(jié)果:陰性
- ---------------
- 檢測姓名:狼王1
- 事件名稱:核酸檢測
- 事件結(jié)果:陰性
- ---------------
- 檢測姓名:狼王2
- 事件名稱:核酸檢測
- 事件結(jié)果:陽性
- ---------------
- 檢測姓名:狼王3
- 事件名稱:核酸檢測
- 事件結(jié)果:陰性
- ---------------
- 檢測姓名:狼王4
- 事件名稱:核酸檢測
- 事件結(jié)果:陽性
- ---------------
- 檢測姓名:狼王5
- 事件名稱:核酸檢測
- 事件結(jié)果:陽性
- ---------------
- 檢測姓名:狼王6
- 事件名稱:核酸檢測
- 事件結(jié)果:陽性
- ---------------
- 檢測姓名:狼王7
- 事件名稱:核酸檢測
- 事件結(jié)果:陰性
- ---------------
- 檢測姓名:狼王8
- 事件名稱:核酸檢測
- 事件結(jié)果:陰性
- ---------------
- 檢測姓名:狼王9
- 事件名稱:核酸檢測
- 事件結(jié)果:陰性
4、分析
代碼依賴關(guān)系如下圖所示:
分別定義了三個接口:事件接口,消息發(fā)布者接口,消息訂閱者接口每個接口有其對應(yīng)的實現(xiàn)。
這樣設(shè)計利于后續(xù)的擴展,在不同的事件和不同的訂閱者以及消息發(fā)布者,都可以進(jìn)行擴展而不影響其他。
5、總結(jié)
優(yōu)點:
1)開閉原則
2)業(yè)務(wù)代碼解耦,具體消息訂閱者和發(fā)布者沒有直接關(guān)聯(lián)。
缺點:
1)多個消費者存在的時候,可能會無法控制順序和時間較長。
好了。今天就說到這了,我還會不斷分享自己的所學(xué)所想,希望我們一起走在成功的道路上!