日韩国产精品99成人不卡在线无毒|狠狠躁夜夜爽一级二级精品|亚洲日日噜噜孕妇中文字幕|日韩久草中文三级片

新聞動態(tài)

設(shè)計(jì)模式系列| 觀察者模式

常見問題 發(fā)布者:ou3377 2021-12-25 10:01 訪問量:315

這篇讓我們來認(rèn)識一下觀察者模式


1、概述

觀察者模式是一種行為設(shè)計(jì)模式, 允許你定義一種訂閱機(jī)制, 可在對象事件發(fā)生時(shí)通知多個(gè) “觀察” 該對象的其他對象。

2、適用場景

1)當(dāng)一個(gè)對象狀態(tài)的改變需要改變其他對象, 或?qū)嶋H對象是事先未知的或動態(tài)變化時(shí), 可使用觀察者模式

2) 當(dāng)應(yīng)用中的一些對象必須觀察其他對象時(shí),可使用該模式。但僅能在有限時(shí)間內(nèi)或特定情況下使用。訂閱者可隨時(shí)加入或離開該列表。

3、實(shí)例

有以下場景:

有一個(gè)小區(qū),需要進(jìn)行核酸檢測。
假設(shè)每個(gè)人通過關(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<>());
        //實(shí)例化接受檢測的用戶
        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("---------------");
            //隨機(jī)檢測結(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)系如下圖所示:

圖片

分別定義了三個(gè)接口:事件接口,消息發(fā)布者接口,消息訂閱者接口每個(gè)接口有其對應(yīng)的實(shí)現(xiàn)。

這樣設(shè)計(jì)利于后續(xù)的擴(kuò)展,在不同的事件和不同的訂閱者以及消息發(fā)布者,都可以進(jìn)行擴(kuò)展而不影響其他。

5、總結(jié)

優(yōu)點(diǎn):

1)開閉原則

2)業(yè)務(wù)代碼解耦,具體消息訂閱者和發(fā)布者沒有直接關(guān)聯(lián)。

缺點(diǎn):

1)多個(gè)消費(fèi)者存在的時(shí)候,可能會無法控制順序和時(shí)間較長。



關(guān)鍵字: 觀察者模式 設(shè)計(jì)模式

文章連接: http://www.hsjyfc.com.cn/cjwt/860.html

版權(quán)聲明:文章由 晨展科技 整理收集,來源于互聯(lián)網(wǎng)或者用戶投稿,如有侵權(quán),請聯(lián)系我們,我們會立即刪除。如轉(zhuǎn)載請保留