zoukankan      html  css  js  c++  java
  • 《设计模式》之观察者模式

    观察者模式

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

    观察者模式就两种角色,一是观察者,二是被观察者( 主题 ),也可以认为是订阅者和发布者。

    收通知的就是观察者。

    如果观察者和被观察者这几个字已被混淆,可以用报纸发布订阅来套。客户是订阅报纸,收报纸的人( 收通知 ),所以客户就是观察者,那么报社就是被观察者了。

    使用

    /**
     * 抽象类
     * @author aodeng-低调小熊猫
     * @since 19-7-15
     */
    public abstract class Customer {
        /**
        * <p>
        * 定义一个抽象方法
        * </p>
        * @author aodeng
        * @since 19-7-15
        */
        public abstract void update();
    
    }
    
    /**
     * 收到通知的观察者客户A
     * @author aodeng-低调小熊猫
     * @since 19-7-15
     */
    public class CustomerA extends Customer {
        @Override
        public void update() {
            System.out.println("我是客户A,我收到报纸了!");
        }
    }
    
    /**
     * 收到通知的观察者客户B
     * @author aodeng-低调小熊猫
     * @since 19-7-15
     */
    public class CustomerB extends Customer {
        @Override
        public void update() {
            System.out.println("我是客户B,我收到报纸了");
        }
    }
    
    /**
     * 被观察者 报社
     * @author aodeng-低调小熊猫
     * @since 19-7-15
     */
    public class NewsOffice {
        private List<Customer> customerList=new ArrayList<>();
    
        public void add(Customer customer){
            this.customerList.add(customer);
        }
    
        /** 
        * <p>
        * 模拟新报纸来了
        * </p> 
        * @author aodeng
        * @since 19-7-15
        */
        public void newspaperCome(){
            this.notifyAllObservers();
        }
    
        public void notifyAllObservers(){
            for (Customer customer : customerList) {
                customer.update();
            }
        }
    }
    

    测试

        public static void main(String[] args) {
            System.out.println("Hello World!");
            NewsOffice newsOffice=new NewsOffice();
            newsOffice.add(new CustomerA());
            newsOffice.add(new CustomerB());
            newsOffice.newspaperCome();
    
        }
        输出:
        Hello World!
        我是客户A,我收到报纸了!
        我是客户B,我收到报纸了
    

    加强

    /**
     * 定义被观察者接口
     * @author aodeng-低调小熊猫
     * @since 19-7-15
     */
    public interface ISubject {
        public void registerObserver(Customer customer);
        public void removeObserver(Customer customer);
        public void notifyObservers();
    
    }
    
    /**被观察者 报社 加强版
     * @author aodeng-低调小熊猫
     * @since 19-7-15
     */
    public class NewsOfficeNiu implements ISubject {
    
        private List<Customer> customerList = new ArrayList<>();
    
        @Override
        public void registerObserver(Customer customer) {
            this.customerList.add(customer);
        }
    
        @Override
        public void removeObserver(Customer customer) {
            customerList.remove(customer);
        }
    
        @Override
        public void notifyObservers() {
            for (Customer customer : customerList) {
                customer.update();
            }
        }
    
        //模拟报纸来了
        public void newspaperCome(){
            this.notifyObservers();
        }
    }
    

    测试

            System.out.println("加强版========");
            ISubject iSubject=new NewsOfficeNiu();
            Customer customera=new CustomerA();
            iSubject.registerObserver(customera);
            iSubject.removeObserver(customera);
            iSubject.registerObserver(new CustomerB());
            ((NewsOfficeNiu) iSubject).newspaperCome();
            
           输出:
           加强版========
           我是客户B,我收到报纸了
    

    Java 提供的观察者模式

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

    copy 一个demo

    //demo
    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,我收到消息啦");
        }
    }
    
    //测试
    Observableoffice = new NewsOffice2();
    Observer observer = new CustomerC();
    
    office.addObserver(observer);
    
    ((NewsOffice2) office).newspaperCome();
    

    总结

    java自带的考虑到了线程安全,但是自己写的很多时候比较方便,有利有弊

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

    2.缺点
    观察者只知道被观察者发生变化,而无法知道是如何发生变化的,比如是修改了 name 字段还是其他,观察者都不知道。
    如果有很多个观察者,一个个通知比较耗时。

    源码

    源码地址:https://github.com/java-aodeng/hope

    本文由低调小熊猫一文多发操作发布! 欢迎关注公众号:低调小熊猫

  • 相关阅读:
    ViewPager留出边 显示左右两边的视图
    Retrofit 2.0 上传文件
    android一个app打开另一个app的指定页面
    Java多线程消费者、生产者的基本思路
    Android 8.0+ 更新安装apk失败的问题
    Android 8.0+ 通知不显示的适配
    android 7.0+ FileProvider 访问隐私文件 相册、相机、安装应用的适配
    android 6.0+ 动态权限 拒绝不再询问后跳转设置应用详情页面
    ViewPager中Fragment的重复创建、复用问题
    Android源码学习(2) Handler之Looper
  • 原文地址:https://www.cnblogs.com/aodeng/p/11778063.html
Copyright © 2011-2022 走看看