zoukankan      html  css  js  c++  java
  • 设计模式(六)_观察者模式

    继续学习设计模式,这个月准备再学习几个重要的设计模式。废话不多说,观察者模式,走起!

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

    • 观察者模式属于行为型模式。行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯

    举例说明

    比如,我们以订阅报纸为例,当你订阅了一份报纸,每天都会有一份最新的报纸送到你的手上。有多少人订阅报纸,报社就会发多少份报纸,这就是典型的订阅-发布模式,报社和订阅报纸的客户就是一对多的依赖关系。

    根据这个例子,简单画下UML类图

    具体代码

    观察者(客户)

    public interface Customer {
    
        public abstract void update();
    }
    
    public class CustomerA implements Customer {
        @Override
        public void update() {
            System.out.println("我是客户A.我收到报纸了");
        }
    }
    
    public class CustomerB implements Customer {
        @Override
        public void update() {
            System.out.println("我是客户B,我收到报纸了");
        }
    }
    

    被观察者(报社)

    public class NewsOffice {
    
        private List<Customer> customers = new ArrayList<>();
    
        public void addCustomer(Customer customer){
            this.customers.add(customer);
        }
    
        //报纸来了
        public void newspaperCome(){
            this.notifyAllObservers();
        }
    
        public void notifyAllObservers(){
            for (Customer customer: customers) {
                customer.update();
            }
        }
    }
    

    测试

    NewsOffice office = new NewsOffice();
    
    Customer customerA = new CustomerA();
    Customer customerB = new CustomerB();
    
    //客户A订阅报纸
    office.addCustomer(customerA);
    // 客户B订阅报纸
    office.addCustomer(customerB);
    
    office.notifyAllObservers();
    

    输出:

    我是客户A.我收到报纸了
    我是客户B,我收到报纸了
    

    观察者模式,最重要的一点,就是要搞清楚谁是观察者,谁是被观察者。

    收通知的就是观察者

    客户是订阅报纸,收报纸的人(收通知) 。所以客户就是观察者,那么报社就是被观察者

    Java中提供的观察者模式

    java 已经为我们提供观察者模式 所需要的类:Observer类 和 Subject 类,只不过在 Java 中 Subject 不叫 Subject,而叫 Observable。

    查看Observable类的结构

    我使用idea,直接ctrl+N 输入Observable,打开Observable类,然后输入alt+7 .就显示类的结构了

    观察源码和我们自己写的代码有什么区别?

    • 保存观察者列表不是用的List
    private Vector<Observer> obs;
    
    • 通知观察者 用了synchronized关键字
    public void notifyObservers(Object arg) {
            /*
             * a temporary array buffer, used as a snapshot of the state of
             * current Observers.
             */
            Object[] arrLocal;
    
            synchronized (this) {
                /* We don't want the Observer doing callbacks into
                 * arbitrary code while holding its own Monitor.
                 * The code where we extract each Observable from
                 * the Vector and store the state of the Observer
                 * needs synchronization, but notifying observers
                 * does not (should not).  The worst result of any
                 * potential race-condition here is that:
                 * 1) a newly-added Observer will miss a
                 *   notification in progress
                 * 2) a recently unregistered Observer will be
                 *   wrongly notified when it doesn't care
                 */
                if (!changed)
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
         }
    

    我们利用java提供的这2个类实现刚刚的情景

    public class NewsOffice2 extends Observable {
    
        /**
         * 模拟报纸来了
         */
        public void newspaperCome(){
            this.setChanged();
            this.notifyObservers();
        }
    }
    
    public class CustomerC implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            System.out.println("我是客户c 我收到报纸了");
        }
    }
    

    测试

            NewsOffice2 office2 = new NewsOffice2();
    
            CustomerC customerC = new CustomerC();
    
            office2.addObserver(customerC);
    
            office2.newspaperCome();
    

    运行结果

    我是客户c 我收到报纸了
    

    优缺点

    优点

    • 观察者和被观察者之间抽象耦合,自有一套触发机制,被观察者无需知道通知的对象是谁,只要是符合观察者接口的就可以

    缺点

    • 观察者只知道被观察发生变化,而无法知道如何变化的
    • 如果存在多个观察者,一个个通知,比较耗时。
  • 相关阅读:
    多线程对各种变量共享(经典)
    offsetHeight/Width clientHeight/Width scrollHeight/Width等高宽算法
    javascript基础-DOM原理
    放弃FreeMark?
    前端项目的开展
    【JAVA错误笔记】
    【JAVA错误笔记】
    【JAVA错误笔记】
    MVC Filter自定义异常(拦截)
    MVC Filter自定义验证(拦截)
  • 原文地址:https://www.cnblogs.com/zhenghengbin/p/9265650.html
Copyright © 2011-2022 走看看