设计模式(十九)观察者模式模式

作者: 我犟不过你 | 来源:发表于2021-01-22 17:16 被阅读0次

    1、概述

    观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。

    2、适用场景

    1)当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化时, 可使用观察者模式。
    2) 当应用中的一些对象必须观察其他对象时, 可使用该模式。 但仅能在有限时间内或特定情况下使用。订阅者可随时加入或离开该列表。

    3、实例

    当前场景:

    有一个小区,需要进行核酸检测。
    假设每个人通过关注公众号获取核酸检测结果。
    

    发布者接口:

    /**
     * 发布接口
     * @date: 2021/1/22
     * @author weirx
     * @version 3.0
     */
    public interface IPublisher {
    
        /**
         * 发布事件
         * @param event
         */
        void publish(IEvent event);
    }
    

    订阅者接口:

    /**
     * 通用订阅接口
     * @date: 2021/1/22
     * @author weirx
     * @version 3.0
     */
    public interface ISubscriber {
    
        /**
         * 查看结果
         */
        void look();
    }
    

    事件接口:

    /**
     * 通用事件接口
     * @date: 2021/1/22
     * @author weirx
     * @version 3.0
     */
    public interface IEvent {
    
        /**
         * 打印事件信息
         */
        void print();
    
    }
    

    消息发送者

    import java.util.List;
    
    /**
     * 消息发送者
     * @date: 2021/1/22
     * @author weirx
     * @version 3.0
     */
    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;
        }
    
        /**
         * 发布消息
         * @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;
        }
    
    }
    

    事件:

    /**
     * 检测事件
     * @date: 2021/1/22
     * @author weirx
     * @version 3.0
     */
    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("事件结果:" + 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;
        }
    }
    

    订阅者:

    /**
     * 订阅者
     * @date: 2021/1/22
     * @author weirx
     * @version 3.0
     */
    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);
        }
    }
    

    客户端:

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 测试类
     * @date: 2021/1/22
     * @author weirx
     * @version 3.0
     */
    public class TestDemo {
    
        public static void main(String[] args) {
            //定义两种结果
            String[] doc = {"阴性", "阳性"};
            //初始化检测事件
            CheckEvent check = new CheckEvent("核酸检测");
            //初始化消息发布者
            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;
            //发布检测结果
            for (int i = 0; i < 10; i++) {
                System.out.println("---------------");
                //随机检测结果
                index = (int) (Math.random() * doc.length);
                check.setSubscriber(users.get(i));
                check.setResult(doc[index]);
                //发布
                publisher.publish(check);
            }
    
        }
    }
    

    结果:

    ---------------
    检测姓名:小0
    事件名称:核酸检测
    事件结果:阴性
    ---------------
    检测姓名:小1
    事件名称:核酸检测
    事件结果:阴性
    ---------------
    检测姓名:小2
    事件名称:核酸检测
    事件结果:阳性
    ---------------
    检测姓名:小3
    事件名称:核酸检测
    事件结果:阴性
    ---------------
    检测姓名:小4
    事件名称:核酸检测
    事件结果:阳性
    ---------------
    检测姓名:小5
    事件名称:核酸检测
    事件结果:阳性
    ---------------
    检测姓名:小6
    事件名称:核酸检测
    事件结果:阳性
    ---------------
    检测姓名:小7
    事件名称:核酸检测
    事件结果:阴性
    ---------------
    检测姓名:小8
    事件名称:核酸检测
    事件结果:阴性
    ---------------
    检测姓名:小9
    事件名称:核酸检测
    事件结果:阴性
    

    4、分析

    代码依赖关系如下图所示:

    TestDemo.png

    分别定义了三个接口:事件接口,消息发布者接口,消息订阅者接口
    每个接口有其对应的实现。

    这样设计利于后续的扩展,在不同的事件和不同的订阅者以及消息发布者,都可以进行扩展而不影响其他。

    5、总结

    优点:
    1)开闭原则
    2)业务代码解耦,具体消息订阅者和发布者没有直接关联。
    缺点:
    1)多个消费者存在的时候,可能会无法控制顺序和时间较长。

    相关文章

      网友评论

        本文标题:设计模式(十九)观察者模式模式

        本文链接:https://www.haomeiwen.com/subject/yigloktx.html