设计模式-行为模式-观察者模式 以及java源码实现以及spring 监听机制的实现

观察者模式:observer pattern
对象存在一对多关系,当一个对象被修改,则自动通知其他依赖它的对象
关键代码:在抽象类中有ArrayList 存放观察者们
在这里插入图片描述

subject
observer
client

package com.example.demo.designpattern.oberver;

import java.util.ArrayList;
import java.util.List;

/**
 * 观察者模式     被观察的对象
 */
public class Subject {
    //被观察的属性状态,当属性变化时要通知观察者们
    private String state;
    //观察者集合,因为需要通知观察者
    private List<AbstractObserver> abstractObserverList = new ArrayList<>();

    public String getState() {
        return state;
    }
    // 被观察的是state的属性,所有当state属性变化时,需要同时观察者
    public void setState(String state) {
        this.state = state;
        this.notifyAllObserves(state);
    }

    private void notifyAllObserves(String state) {
        for(AbstractObserver abstractObserver:abstractObserverList) {
            abstractObserver.update();
        }
    }
    //将观察者加入集合中
    public void add(AbstractObserver abstractObserver) {
        this.abstractObserverList.add(abstractObserver);
    }
}
















package com.example.demo.designpattern.oberver;

/**
 * 抽象观察者,解耦
 */
public abstract class AbstractObserver {
    //定义一个对象,在实现类构造方法中传入对象
    public Subject subject;
    public abstract void update();
}

package com.example.demo.designpattern.oberver;

/**
 * 具体的观察者,实现抽象类
 */
public class Observer1 extends AbstractObserver{
    //观察者们需要将自己加入观察对象的观察集合中
    //传入观察者对象
    public Observer1(Subject subject){
        this.subject = subject;
        subject.add(this);
    }
    @Override
    public void update() {
        System.out.println("观察者1收到了状态变化通知");
    }
}


package com.example.demo.designpattern.oberver;

public class Observer2 extends AbstractObserver{
    public Observer2(Subject subject) {
        this.subject = subject;
       subject.add(this);
    }
    @Override
    public void update() {
        System.out.println("观察者2收到了状态变化通知");
    }
}


package com.example.demo.designpattern.oberver;

public class ObserverDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();
        new Observer1(subject);
        new Observer2(subject);
        subject.setState("1");
    }
}

java源码已经内置了观察者模式,我们使用时只需要去继承即可

主题类 Observable Observable内部使用Vector来存储注册的观察者实例,是线程安全的。
分析下 主题类 Observable源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package java.util;

public class Observable {
    //只有changed为true才开启通知
    private boolean changed = false;
   //观察者集合使用vector保证线程安装
    private Vector<Observer> obs = new Vector();

    public Observable() {
    }
   //将观察者加入集合

    public synchronized void addObserver(Observer var1) {
        if (var1 == null) {
            throw new NullPointerException();
        } else {
            if (!this.obs.contains(var1)) {
                this.obs.addElement(var1);
            }

        }
    }
   //删除观察者
    public synchronized void deleteObserver(Observer var1) {
        this.obs.removeElement(var1);
    }
   // 主题类状态发生变化时通知观察者
    public void notifyObservers() {
        this.notifyObservers((Object)null);
    }

    public void notifyObservers(Object var1) {
        Object[] var2;
        synchronized(this) {
            if (!this.changed) {
                return;
            }
    //集合转数组遍历
            var2 = this.obs.toArray();
            this.clearChanged();
        }

        for(int var3 = var2.length - 1; var3 >= 0; --var3) {
            ((Observer)var2[var3]).update(this, var1);
        }

    }

    public synchronized void deleteObservers() {
        this.obs.removeAllElements();
    }
   // 将changed变成true
    protected synchronized void setChanged() {
        this.changed = true;
    }

    protected synchronized void clearChanged() {
        this.changed = false;
    }

    public synchronized boolean hasChanged() {
        return this.changed;
    }

    public synchronized int countObservers() {
        return this.obs.size();
    }
}

观察者抽象类:Observer 具体的实现需要我们自己实现

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package java.util;

public interface Observer {
    void update(Observable var1, Object var2);
}

下面就按照java自带的观察者模式改造上述案例

package com.example.demo.designpattern.oberver.javaobserver;

import java.util.Observable;

public class JavaSubject extends Observable {
    //定义我们观察的属性
    private String state;

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
        statementChanged();
    }

    private void statementChanged() {
        //将changed改成true
        setChanged();
        //通知其他观察者
        notifyObservers();
    }
}


package com.example.demo.designpattern.oberver.javaobserver;

import java.util.Observable;
import java.util.Observer;

public class Observer1 implements Observer {
    private Observable observable;
    public Observer1(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("观察者1收到了状态变化通知");
    }
}

package com.example.demo.designpattern.oberver.javaobserver;

import com.example.demo.designpattern.oberver.Subject;

public class JavaSubjectDemo {
    public static void main(String[] args) {
        JavaSubject javaSubject = new JavaSubject();
        new Observer1(javaSubject);
        javaSubject.setState("1");
    }

}

借用java自带的观察者模式可以很轻松就实现了通知

基于观察者模式的spring监听机制

spring 中观察者模式的实现:
对象说明:
applicationContext spring核心容器对象(beanfactory也是容器对象) 事件监听中 ApplicationContext 可以作为事件的发布者,也就是事件源 因为 ApplicationContext 继承自 ApplicationEventPublisher。
Spring 中默认存在以下事件,他们都是对 ApplicationContextEvent 的实现(继承自ApplicationContextEvent):
ContextStartedEvent:ApplicationContext 启动后触发的事件;
ContextStoppedEvent:ApplicationContext 停止后触发的事件;
ContextRefreshedEvent:ApplicationContext 初始化或刷新完成后触发的事件;
ContextClosedEvent:ApplicationContext 关闭后触发的事件。在 ApplicationEventPublisher 中定义了事件发布的方法:publishEvent(Object event)
applicationEvent 事件对象 (contextrefreshedEvent 容器刷新对象) 主题类
applicationListener 事件监听对象 观察者类(接口抽象) 继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent。当监听的事件发生后该方法会被执行
ApplicationEventMulticaster 事件管理,用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 Applicationcontext 发布的 Event 广播给它的监听器列表。

案例:  主题
package com.example.demo.designpattern.oberver.springobserver;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;

import java.time.Clock;

public class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
        System.out.println("MyEvent 构造器执行");
    }

}
监听对象: 可以继承ApplicationListener<MyEvent>实现
package com.example.demo.designpattern.oberver.springobserver;

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyListenerA implements ApplicationListener<MyEvent> {

    @Override
    public void onApplicationEvent(MyEvent event) {
        System.out.println("MyListenA");
    }
}
可以使用注解 @EventListener 实现
package com.example.demo.designpattern.oberver.springobserver;

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MylistenerB {
    @EventListener
    public void onApplicationEvent(MyEvent event) {
        System.out.println("MylistenB");
    }
}
发布: 注明在bean加载过程中实现了ApplicationContextAware的接口,会在bean实例化完成后调用setApplicationContext方法,传入ApplicationContext  bean工厂,然后调用publishEvent 发布事件

package com.example.demo.designpattern.oberver.springobserver;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;

@Component(value ="myPublisher")
public class MyPublisher implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    public void publishEvent(ApplicationEvent event){
        System.out.println("publish event");
        applicationContext.publishEvent(event);
    }
}
测试:
package com.example.demo.designpattern.oberver.springobserver;

import com.example.demo.designpattern.oberver.springobserver.MyEvent;
import com.example.demo.designpattern.oberver.springobserver.MyPublisher;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;

@RestController
@RequestMapping(value = "kangtest")
public class SpringObserverController {
    @RequestMapping(value = "observer", method = RequestMethod.GET)
    public void getText() {
        HttpServletRequest request =         ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        ServletContext servletContext = request.getSession().getServletContext();
        WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        MyPublisher myPublisher = (MyPublisher)applicationContext.getBean("myPublisher");
        myPublisher.publishEvent(new MyEvent(this));

//        new MyEvent(this);
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值