zoukankan      html  css  js  c++  java
  • 设计模式:观察者模式

    定义

    观察者模式(Observer )又叫做发布-订阅模式。定义一种一对多的依赖关系,一个主题对象可以被多个观察者对象同时监听,使得每当主题对象的状态变化时,所有依赖它的对象都会得到通知并被自动更新,属于行为型设计模式。

    场景:

    • 当一个抽象模型包含两方面的内容,其中一方面依赖另一方面。
    • 其他一个或者多个对象的变化依赖另一个对象的变化
    • 实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接受该广播
    • 多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知

    场景一

    现系统传来一份报告,报告需要发送给订阅了报告的客户。

    下面是非观察者模式的代码实现:

    //系统类
    public class System {
        //报告
        protected String report;
    
        public void setReport(String report) {
            this.report = report;
            //发送报告
            send();
        }
        public void send(){
        }
    }
    
    //用户
    public class User {
        private String name;
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public void getReport(String report){
            java.lang.System.out.println("user:"+name+"收到报告====>report:"+report);
        }
        public User(String name) {
            this.name = name;
        }
    }
    //发送者
    public class Sender extends System{
    
        private User user = new User("A");
        private User user2 = new User("B");
        private User user3 = new User("C");
    
        @Override
        public void send() {
            user.getReport(super.report);
            user2.getReport(super.report);
            user3.getReport(super.report);
        }
    }
    

    测试:

        public static void main(String[] args) {
            System system = new Sender();
            system.setReport("每日资讯");
        }
    

    image-20201227145147427

    但是以上代码有严重缺陷:

    • 如果需要增加或者减少订阅者,势必需要修改源代码,违反了开闭原则

    场景二

    下面则用观察者模式实现该场景:

    //发布者接口
    interface Subject<String> {
        //注册观察者
        public void register(Observer observer);
        //删除观察者
        public void remove(Observer observer);
        //通知
        public void notify(String report);
    }
    //观察者
    interface Observer<String> {
        //被通知
        public void notified(String report);
    }
    
    //发布者实现
    public class System<String> implements Subject<String>{
        private List<Observer> observers = new ArrayList<>();
        protected String report;
    
        @Override
        public void register(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void remove(Observer observer) {
            observers.remove(observer);
        }
    
        @Override
        public void notify(String report) {
            observers.forEach(observer -> observer.notified(report));
        }
    }
    //订阅者实现
    public class User<String> implements Observer<String>{
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        User(String name) {
            this.name = name;
        }
    
        @Override
        public void notified(String report) {
            java.lang.System.out.println("user:"+name+"收到报告====>report:"+report);
        }
    }
    

    测试:

        public static void main(String[] args) {
            Subject<String> subject = new System<>();
            Observer<String> observer = new User<>("张三");
            Observer<String> observer2 = new User<>("李四");
            subject.register(observer);
            subject.register(observer2);
            subject.notify("每日咨询");
            subject.remove(observer2);
            subject.notify("财经视野");
        }
    

    image-20201227151618615

    uml类图:

    image-20201227151822604

    jdk中实现的观察者模式

    代码也很简单,不过多介绍

    //订阅者
    public class Observable {
        private boolean changed = false;
        private Vector<Observer> obs;
    
        public Observable() {
            obs = new Vector<>();
        }
    
        public synchronized void addObserver(Observer o) {
            if (o == null)
                throw new NullPointerException();
            if (!obs.contains(o)) {
                obs.addElement(o);
            }
        }
    
        public synchronized void deleteObserver(Observer o) {
            obs.removeElement(o);
        }
    
        public void notifyObservers() {
            notifyObservers(null);
        }
    
        public void notifyObservers(Object arg) {
            Object[] arrLocal;
    
            synchronized (this) {
                if (!changed)
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
    
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
        }
    
        public synchronized void deleteObservers() {
            obs.removeAllElements();
        }
    
        protected synchronized void setChanged() {
            changed = true;
        }
    
        protected synchronized void clearChanged() {
            changed = false;
        }
    
        public synchronized boolean hasChanged() {
            return changed;
        }
    
        public synchronized int countObservers() {
            return obs.size();
        }
    }
    
    //观察者
    public interface Observer {
        void update(Observable o, Object arg);
    }
    

    我们可以继承Observable类和实现Observer接口,以实现业务逻辑。

  • 相关阅读:
    [转]windows7远程桌面连接失败:发生身份验证错误。要求的函数不受支持
    SNMP协议学习笔记
    Sublime for MacOS 使用技巧
    Git常用操作
    罗技K380连接Win10(MacBookPro双系统)系统失败
    Git知识点汇总
    开发工作中提高效率的一些方式
    css
    IO多路复用
    进程
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14197430.html
Copyright © 2011-2022 走看看