• java 观察者模式


                                《Head First 设计模式》学习中

       观察者模式

    • 定义了对象之间的一对多依赖,这样一来,当一个对象状态改变状态时,他的所有依赖都会收到通知并自动更新。

       观察者模式结构图

                      

    • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
    • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
    • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
    • ConcrereObserver:具体观察者,是实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

     简单实现

      比如: 你想给你的客户推送一天暖心信息

    抽象观察者(Observer)

    里面定义了一个更新的方法:

    package com.Observer.model;
    
    public interface Observer {
        
        void update(String information); 
    }

    具体观察者(ConcrereObserver)

    用户是观察者,里面实现了更新的方法:

    package com.Observer.model;
    
    public class userObserver implements Observer {
        
        private String user;
        
        public userObserver(String user){
            this.user = user;
        }
        
        @Override
        public void update(String information) {
            System.out.println("用户" +user + "  " + information);
        }
    
        public String getUser() {
            return user;
        }
    
        public void setUser(String user) {
            this.user = user;
        }
    
        
    }

    抽象被观察者(Subject)

    抽象主题,提供了add、delete、notify三个方法:

    package com.Observer.model;
    
    public interface Subject {
        
        void addUser(Observer obs);
        
        void deleteUser(Observer obs);
        
        void notify(String information);
    }

    具体被观察者(ConcreteSubject)

    具体主题(具体被观察者),里面存储了所有用户,并实现了抽象主题中的方法:

    package com.Observer.model;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class SubscriptionSubject implements Subject {
    
        private List<Observer> list = new ArrayList<>();
        
        @Override
        public void addUser(Observer obs) {
            userObserver user = (userObserver) obs;
            System.out.println("增加用户:" + user.getUser());
            list.add(obs);
        }
    
        @Override
        public void deleteUser(Observer obs) {
            userObserver user = (userObserver) obs;
            System.out.println("删除用户:" + user.getUser());
            list.remove(obs);
        }
    
        @Override
        public void notify(String information) {
            for (Observer obs : list) {
                obs.update(information);
            }
        }
    
    }

    测试:

    package com.Observer.model;
    
    public class TestObserver {
        public static void main(String[] args) {
            
            //创建对象
            SubscriptionSubject sub = new SubscriptionSubject();
            
            //模拟用户
            userObserver inUpdate = new userObserver("张三");
            userObserver inUpdate1 = new userObserver("李四");
            userObserver inUpdate2 = new userObserver("王五");
            
            //添加用户
            sub.addUser(inUpdate);
            sub.addUser(inUpdate1);
            sub.addUser(inUpdate2);
            
            //推送消息
            sub.notify("天冷了,出门在外多加衣,注意保暖");
            
            //删除用户
            sub.deleteUser(inUpdate);
            
            //再次推送消息
            sub.notify("出门在外照顾好自己");
            
            
        }
    }

    效果:

    增加用户:张三
    增加用户:李四
    增加用户:王五
    用户张三  天冷了,出门在外多加衣,注意保暖
    用户李四  天冷了,出门在外多加衣,注意保暖
    用户王五  天冷了,出门在外多加衣,注意保暖
    删除用户:张三
    用户李四  出门在外照顾好自己
    用户王五  出门在外照顾好自己

     设计原则描述

    • 找出程序中会变化的方面,然后将其和固定不变的方面相分离

        在观察者模式中,会改变的是主题的状态,以及观察者的数目,用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题,这叫提前规则。

    • 针对接口编程,而不是针对实现编程

        主题与观察者都使用接口,观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者,这样可以让两者之间运作正常,又同时具有松耦合                   的特点。

    • 多用组合少用继承

    ·     观察者模式利用 “组合” 将许多观察者组合进主题中,对象之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式产生。

    使用场景

    • 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
    • 事件多级触发场景。
    • 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

    优点

      解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。

    缺点

      在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息           的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

      参考   http://blog.csdn.net/itachi85/article/details/50773358

  • 相关阅读:
    泡泡H5这封企业剪彩活动邀请函好像挺专业!
    教你 Shiro + SpringBoot 整合 JWT
    Thymeleaf 获取后端Model中的数据
    SpringBoot 之 普通类获取Spring容器中的bean ,
    如何用JS判断网页中某个id的网页元素是否存在(两种写法 jQuery写法和原始写法:
    前台请求不带cookie的问题解决方案大汇总
    js访问函数内部的变量(三种方法)
    源码分析:若依用户 user_id查询返回除了用户表,为何还带有部门dept和角色role表呢
    关于若依前端分页首次使用BootstrapPager 即bootstrap扩展插件
    关于若依需要验证码,PostMan是如何登陆流程
  • 原文地址:https://www.cnblogs.com/chenlizhi/p/7806375.html
Copyright © 2020-2023  润新知