美文网首页hello world
设计模式-观察者模式和事件机制

设计模式-观察者模式和事件机制

作者: slicn | 来源:发表于2018-04-21 01:26 被阅读0次

概念

观察者模式

百科这样解释:一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法(updata)来实现。具有典型的一对多的关系。使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知进行更新。观察者模式的目标对象中保留了观察者的集合,当被观察者对象的状态发生变化时,会遍历该集合,然后通知(updata)观察者对象得到更新。强调对象行为 具有观察者和目标的解耦,动态联动(动态注册控制动作);广播通信(面向所有的观察者)的优点 image.png

发布/订阅模式(比生产消费更抽象)参考

基于典型观察者模式实现的生产者和消费者弊端:观察者模式中观察者需要直接订阅目标事件(直接引用目标状态),改变后直接接收响应,由于函数调用是同步的(阻塞),在消费者的方法没有返回之前,生产者只好一直等在那边,阻塞进程。 生产者和消费者可以是两个独立的并发主体。生产者把制造出来的数据往缓冲区一丢,就可以再去生产下一个数据,并不用关心消费者状态; 发布订阅模式就类似的多了一个发布通道(调度中心),一方面从生产者接收事件一方面向订阅者发布事件。 image.png
1. 观察者模式的模板
设计阶段 image.png
//目标对象,它持有观察者抽象的集合
public class Subject {

    //定义抽象目标的状态
    private String subjectState;
   //用来保存注册的观察者集合
    private List<Observer_> observerList = new ArrayList<Observer_>();


    //当状态改变时去通知
    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
        this.notifyObservers(); //通知
    }

    //添加观察者
    public void attach(Observer_ observer){
        observerList.add(observer);
    }
    //删除观察者
    public void detach(Observer_ observer){
        observerList.remove(observer);
    }

    //通知所有的观察者
    public void notifyObservers(){
        for (Observer_ observer: observerList){
            observer.updata(this);
        }
}

}

//观察者
public class Observer_ {

    //定义抽象的状态
    private String observerState;

    //获取目标类的状态同步到观察者状态中
    public void updata(Subject subject){
        observerState = subject.getSubjectState();
        System.out.println("通知:" + observerState);
    }
}

public class Client {

    @Test
    public void testObserver(){
        //1 创建目标
        Subject subject = new Subject();
        //2 创建观察者
        Observer_ observer1 = new Observer_();
        observer1.setObserverState("observer1");
        //注册
        subject.attach(observer1);
        //通知
        subject.setSubjectState("这是观察者模式");
    }

}

image.png

以上就是典型的观察者模式的模板

2. 区别对待观察者场景的问题

需求:最近经常加班,身为项目经理的你决定给大家买宵夜,张三只要鸡翅,李四想要鸡翅或者汉堡。这里宵夜种类就是目标,张三李四就是观察者,如果通过以上代码,是所有注册都会被通知,这显然是不合理的。代码修改如下:

观察者的接口
//观察者接口定义一个更新接口的方法,目标发生改变时通知观察者进行调用
public interface Observer {

    //更新的接口
    void update(SupperObject objecr);
    //设置和取得观察者名称
    void setObserverName(String observerName);

    String getObserverName();
}
抽象的目标类
public abstract class SupperObject {

    //持有的观察者集合
    public List<Observer> observers = new ArrayList<Observer>();

    //添加 删除 观察者
    public void attach(Observer observer){
        observers.add(observer);
    }
    public void detach(Observer observer){
        observers.remove(observer);
    }
    //具体的提醒在子类逻辑中完成
    protected abstract void notifyObservers();
    
}
 //具体的目标实现类
public class ConcreteSupperSubject extends SupperObject {

    //定义宵夜的变量,鸡翅,汉堡, 就是根据这个变量进项更新(目标状态)
     private String supperContent;


    @Override
    protected void notifyObservers() {
        //循环所有注册的观察者
        for (Observer observer:observers){
            //定义业务逻辑
            //1 .如果鸡翅就通知张三和李四,2.如果汉堡就只通知李四,3.其他都不通知
            if ("鸡翅".equals(this.getSupperContent())){
                if ("张三".equals(observer.getObserverName())){
                    observer.update(this);
                }
                if ("李四".equals(observer.getObserverName())){
                    observer.update(this);
                }
            }
            if ("汉堡".equals(this.supperContent)){
                if ("李四".equals(observer.getObserverName())){
                    observer.update(this);
                }
            }

        }
    }

     public String getSupperContent() {
         return supperContent;
     }

     public void setSupperContent(String supperContent) {
         this.supperContent = supperContent;
         this.notifyObservers(); //通知 区别对待观察者
     }
 }
//观察者的具体实现
public class ConcreteObserver implements Observer{

    //定义观察者名称 ,宵夜情况,提醒内容
    private String observerName;
    private String supperContent;   //目标处获取的状态
    private String remindThing;


    @Override
    public void update(SupperObject object) {
        //获取目标的状态
        supperContent =  ((ConcreteSupperSubject)object).getSupperContent();
        System.out.println(observerName+"收到了"+supperContent+remindThing);
    }
}
    @Test
    public void testSupperClient(){
        //创建目标
        ConcreteSupperSubject supperSubject = new ConcreteSupperSubject();
        //创建观察者
        ConcreteObserver zhangsan = new ConcreteObserver();
        zhangsan.setObserverName("张三");
        zhangsan.setRemindThing("鸡翅真好吃!");
        ConcreteObserver lisi = new ConcreteObserver();
        lisi.setObserverName("李四");
        lisi.setRemindThing("夜宵不错,吃饱了可以好好干活了");
        //注册
        supperSubject.attach(zhangsan);
        supperSubject.attach(lisi);
        //发布 鸡翅,汉堡
        supperSubject.setSupperContent("汉堡");
    }
image.png image.png
观察者模式总结
  1. 存在目标对象和观察者两个概念,做到解耦,但通知却依赖了抽象的观察者,假如观察者无法抽象就无法通知更新。
  2. 所有的观察者的动作都一样。如果不一样就不能实现

事件机制

事件机制 就可以解决以上的问题,不需要观察者的抽象。通过相应的listener代替观察者,类似观察者模式却解耦目标和观察。一般把事件对象作为业务接口的参数,再根据相应的条件触发
事件机制一般需要3个角色,事件触发源(source)、事件状态对象(event)、处理逻辑(listener)
在spirng 中ServletContextListener接口通过web中的listener就可以在web启动时初始化spirng也是事件的一种应用。

  1. 定义事件类
//定义的事件状态类 也可以继承java util 中的event
public class MyEvent {

    //事件对象
    private Object obj;
    //状态即触发条件
    private String state;

    /**
     * Constructs a prototypical MyEvent.
     *
     * @param source The object on which the MyEvent initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public MyEvent(Object source, String state) {
        //super(source);
        this.obj = source;
        this.state = state;
    }
}
  1. 定义事件源handler
public class EventSource {

    //保存监听器的列表,类似观察者模式中保存所有观察者的集合;子类可以保存自己的监听器。
    private Collection listenets;

    //注册监听器
    public void addEventListener(EventListener e){
        if (listenets == null){
            listenets = new HashSet();
        }
        listenets.add(e);
    }

    //删除监听
    public void removeListener(EventListener e){
        if (listenets != null){
            listenets.remove(e);
        }
    }


    /** 根据触发的条件进行事件的执行
     * @param state 触发条件
     */
    protected void fireEvent(String state){
        if (listenets != null){
            MyEvent event = new MyEvent(this,state);
            notifyA(event);
        }
    }

    /**
     * 事件具体的执行
     * @param e 定义的事件
     */
    public void notifyA(MyEvent e){
        Iterator iterator = listenets.iterator();
        while (iterator.hasNext()){
            //实例监听器对象,并调用监听器的方法
            EventListener evt = (EventListener) iterator.next();
            evt.handEvent(e);
        }
    }
}
  1. 定义监听器,把事件作为参数,也是和观察者模式的区别
public interface EventListener{
    //把事件对象作为参数
    void handEvent(MyEvent e);
}
  1. 实现listener 接口,定义业务逻辑
public class Mylistener implements EventListener {


    @Override
    public void handEvent(MyEvent e) {
        //todo 使用if做逻辑控制
        if (e.getState() != null && e.getState() == "hi" ){
            System.out.println(" hi ,java事件机制");
        }
    }
}
public class Mylistener2 implements EventListener {
    @Override
    public void handEvent(MyEvent e) {
        if (e.getState() != null && e.getState().equals("h")){
            System.out.println(" 我是被 "+e.getState()+" 触发的");
        }
    }
}
  1. 测试
 public static void main(String[] args){
        //事件源
        EventSource source = new EventSource();

        /*
        * 当有需要的事件要被触发时就需要编写并注册 相关的listener
        * 这也是事件的弊端
        * */
        source.addEventListener(new Mylistener());
        source.addEventListener(new Mylistener2());
        //根据状态触发
        source.fireEvent("hi");
        source.fireEvent("h");

    }

相关文章

  • 在Spring中使用事件机制

    在Spring中使用事件机制 1. 事件机制 事件机制的底层设计模式是观察者模式,观察者设计模式定义了对象间的一种...

  • Guava EventBus实现原理

    开篇 EventBus是Guava的事件处理机制,是设计模式中的观察者模式的优雅实现。对于事件监听和发布订阅模式,...

  • Spring 内置事件

    ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和App...

  • Spring 事件机制概述

    Spring 事件机制是观察者模式的典型应用,本文将由浅入深从观察者模式、java事件机制、Spring事件机制三...

  • 深入理解 Spring 的事件发布监听机制

    1. 什么是事件监听机制 在讲解事件监听机制前,我们先回顾下设计模式中的观察者模式,因为事件监听机制可以说是在典型...

  • Java - 事件处理机制

    Java - 事件处理机制 一、观察者模式 了解事件和监听,需要先了解观察者模式。 接下来介绍一个观察者模式的场景...

  • S6.观察者模式

    观察者模式 观察者模式是一种行为设计模式,主要用于实现一种订阅机制,可在目标事件发生变化时告知所有观察此事件的对象...

  • Guava——EventBus

    EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监...

  • EventBus

    EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监...

  • guava EventBus使用

    EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监...

网友评论

    本文标题:设计模式-观察者模式和事件机制

    本文链接:https://www.haomeiwen.com/subject/djirkftx.html