• [工作中的设计模式]观察者模式observer


    一、模式解析

      观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

      观察者模式又叫订阅发布模式,从模式理解上来讲,订阅发布模式更好的体现了此模式的含义,因为在我的理解中,观察者和被观察者的关系是,观察者应该时时关注被观察者的动向,如果被观察者发生了变化,那么观察者应该发生对应的关系,比如看球,每个观众都在观察场上局势,如果球进了,有些观众或鼓掌,有些会欢呼,甚至有些会luoben。。这时候并不需要人告诉他们球进了。相反从订阅发布角度来讲,订阅者提供自己的信息给发布者,发布者向这些订阅者发布信息。最与此接近的实际例子为:订阅报纸后,每天邮递员会将报纸投递给订阅者。

    二、模式代码

    1、抽象观察者/抽象订阅者

    package observer.patten;
    /**
     * 监听者,实现update方法,update方法会在被监听者变化是主动调用
     * @author zjl
     * @time 2016-1-25
     *
     */
    public interface Observer {
        public void update();
    }

    2、观察者/订阅者

    package observer.patten;
    
    public class ConcreteObserver implements Observer {
    
        @Override
        public void update() {
            System.out.println("我是监听者,收到了被监听者的变化");
        }
    
    }

    3、抽象被观察者/抽象发布者

    package observer.patten;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    public abstract class Obserable {
        List<Observer> list=new ArrayList<Observer>();//使用list保存被观察者集合
        public void attach(Observer observer){
            list.add(observer);
        }
        public void detach(Observer observer){
            list.remove(observer);
        }
        //notify似乎与jdk底部方法冲突,不能重写
        public void notify1(){
            for(Observer observer:list){
                observer.update();
            }
        }
    }

    4、被观察者/发布者

    package observer.patten;
    
    public class ConcreteObserable extends Obserable {
        public void doSomething(){
            System.out.println("被观察者做了一些事情");
            this.notify1();
        }
    }

    5、客户端代码

    package observer.patten;
    
    public class Client {
        public static void main(String[] args) {
            ConcreteObserable obserable=new ConcreteObserable();
            Observer observer=new ConcreteObserver();
            obserable.attach(observer);
            obserable.doSomething();
        }
    }

    6、执行结果

    被观察者做了一些事情
    我是监听者,收到了被监听者的变化

    三、应用场景

    对于观察者模式很容易想到的就是界面设计中对于各种事件的应用,比如点击按钮后可以执行一些方法或者事件,我们简单看下jdk底层,确实采用观察者模式进行实现,此处简单模拟下原理

    四、场景代码

    1、定义抽象的按钮类,在类里保存事件列表

    package observer.example;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    public abstract class AbstractButton {
        public List<ActionListener> list=new ArrayList<ActionListener>();
        public void addActionListener(ActionListener actionListener){
            if(!list.contains(actionListener)){
                list.add(actionListener);
            }
        }
        public void removeActionListener(ActionListener actionListener){
            if(list.contains(actionListener)){
                list.remove(actionListener);
            }
        }
        
        public void fireActionPerformed(){
            for(ActionListener actionListener:list){
                actionListener.actionPerformed();
            }
        }
        
        
    }

    2、定义按钮

    package observer.example;
    
    public class Button extends AbstractButton {
        
        public void click(){
            this.fireActionPerformed();
        }
    }

    3、定义点击事件的接口

    package observer.example;
    
    public interface ActionListener {
        public void actionPerformed();
    }

    4、定义按钮事件

    package observer.example;
    
    public class ClickActionListener1 implements ActionListener {
    
        @Override
        public void actionPerformed() {
            System.out.println("按钮被点击了,打开新的页面");
        }
    
    }

    5、客户端代码

    package observer.example;
    
    public class Client {
        public static void main(String[] args) {
            Button button=new Button();
            button.addActionListener(new ClickActionListener1());
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed() {
                    System.out.println("原始页面关闭");
                }
            });
            button.click();
        }
    }

    6、结果

    按钮被点击了,打开新的页面
    原始页面关闭

    五、一点分析

    1、如实例所言,对于监听者的创建,可以采取内部类形式,不过这样有两个坏处,1)无法获取添加的监听者指针,也就无法进行删除操作,2)内部类很容易造成java的代码的混乱,所以不建议使用。

    2、如实例中,想要给一个按钮不仅添加点击事件,同时添加焦点事件等,jdk给出的实例为分别编写addFocusListener,addActionListener 等方法来分别事件各种事件的添加,但是我们对比js的时候,发现js其实只有一个方法,使用addEventLister(eventType,fn)就可以完成所有事件添加,所以下章重点讨论java的事件委托。

  • 相关阅读:
    阻塞队列整理
    List与Map整理
    2、Redis中的链表
    【观点】从曾成杰案看民间金融的高风险与银行缺失的机制创新
    林权抵押贷款政策出台 将实现林业资源变资本
    从《男生传递微笑给女生的故事》想到的流程梳理与优化
    落实制度靠流程<摘自平安50万人的执行力>
    vue踩坑- 报错npm ERR! cb() never called!
    vue踩坑-This dependency was not found
    vue踩坑- 报错npm ERR! cb() never called!
  • 原文地址:https://www.cnblogs.com/jyyzzjl/p/5182575.html
Copyright © 2020-2023  润新知