Java设计模式-行为型设计模式-观察者模式

Java设计模式-行为型设计模式-观察者模式

从这一专栏开始将学习设计模式,上课学习和自己总结归纳的笔记将总结出来供大家参考。
参考书籍:《设计模式就该这样学》

其他文章:

Java设计模式-UML类图 Java设计模式-七大架构设计原则-开闭原则
Java设计模式-七大架构设计原则-依赖倒置原则 Java设计模式-七大架构设计原则-单一职责原则
Java设计模式-七大架构设计原则-接口隔离原则 Java设计模式-七大架构设计原则-最少知道原则(迪米特法则)
Java设计模式-七大架构设计原则-里氏替换原则和合成复用原则 Java设计模式-创建型设计模式-简单工厂模式
Java设计模式-创建型设计模式-工厂方法模式(工厂模式) Java设计模式-创建型设计模式-抽象工厂模式
Java设计模式-创建型设计模式-建造者模式 Java设计模式-创建型设计模式-原型模式
Java设计模式-创建型设计模式-单例模式 Java设计模式-结构型设计模式-适配器模式
Java设计模式- 结构型设计模式-享元模式 Java设计模式- 结构型设计模式-外观模式
Java设计模式- 结构型设计模式-桥接模式 Java设计模式-结构型模式设计模式-组合模式
Java设计模式-行为型设计模式-观察者模式

一、行为型设计模式

在GOF23种设计模式中,有三种类型的设计模式,分别是:创建型设计模式、结构型设计模式、行为型设计模式

在GoF23种设计模式中属于行为型设计模式:

Chain of Responsibility ( 责任链模式 )、Command ( 命令模式 )、Interpreter ( 解释器模式 ) 、Iterator ( 迭代器模式 )、Mediator ( 中介者模式 ) 、Memento ( 备忘录模式 ) 、Observer ( 观察者模式 )、State ( 状态模式 ) 、Strategy ( 策略模式 )、TemplateMethod ( 模板方法 )、Visitor ( 访问者模式 )11种模式。

二、观察者模式

1.观察者模式定义

观察者模式(Observer Pattern):又叫做发布-订阅模式(Publish/Subscribe pattern)、模型-视图(Model/View pattern)。定义一种一对多的依赖关系,一个主题对象可以被多个观察值对象同时监听,使得每当主题对象状态变化时,所有依赖它的对象都会得到通知并被自动更新。

在GoF23种设计模式中属于行为型设计模式:

其中包括:Chain of Responsibility ( 责任链模式 )、Command ( 命令模式 )、Interpreter ( 解释器模式 ) 、Iterator ( 迭代器模式 )、Mediator ( 中介者模式 ) 、Memento ( 备忘录模式 ) 、Observer ( 观察者模式 )、State ( 状态模式 ) 、Strategy ( 策略模式 )、TemplateMethod ( 模板方法 )、Visitor ( 访问者模式 )11种模式。

2.观察者模式的角色

抽象主题(ISubject):指被观察的对象,一般是一个抽象类或者是接口,定义了增加、删除、通知观察者对象的方法。

具体主题(ConcreteSubject):具体被观察的对象,当其内部状态变化的时候,会通。已注册的观察者。

抽象观察者(IObserver):定义了响应通知的更新方法。

具体观察者(ConcreteObserver):当得到状态更新的通知时,会自动做出响应。

3.观察者模式的特点

优点:

观察者和被观察者是松耦合的,符合依赖倒置原则(高层模块不应该依赖底层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象);

分离了观察者和被观察者,并且建立了一套触发机制,使得被观察者数据的变化可以响应到多个观察者上;

实现了一对多的通信机制,支持事件处理机制,支持兴趣分发机制,当被观察者触发事件时,只有感兴趣的观察者可以接收到通知。

缺点:

如果观察者的数量过多,则事件通知会耗费更多的时长;
事件通知呈线性关系,如果其中一个观察者处理事件卡壳,则会影响后续的观察者修改该事件;
如果观察者和被观察者之间存在循环依赖,则可能导致两者之间循环调用导致系统崩溃。

观察者模式的应用场景:

起床闹钟设置(如果一个人设置了一个闹钟,那么便会被闹钟提醒,那么闹钟就是被观察者,用户就是观察者);

朋友圈点赞提醒(微信朋友圈点赞之后,你就是观察者,微信的那条朋友圈就是被观察者);

网购APP商品降价通知推送(网购平台上,关注某个商品,当商品降价时,会收到通知)。

4.观察者模式的类图

在这里插入图片描述

5.观察者模式的通用写法

/**
 * 抽象观察者
 */
interface Observer{
    void response();
}

/**
 * 具体观察者A
 */
class ConcreteObserverA implements Observer{
    @Override
    public void response() {
        System.out.println("具体观察者A作出反应!");
    }
}

/**
 * 具体观察者B
 */
class ConcreteObserverB implements Observer{
    @Override
    public void response() {
        System.out.println("具体观察者B作出反应!");
    }
}

/**
 * 抽象主题(被观察者)
 */
abstract class Subject{
    protected List<Observer> observers = new ArrayList<>();

    /**
     * 增加观察者方法
     * @param observer
     */
    public void add(Observer observer){
        observers.add(observer);
    }

    /**
     * 删除观察者方法
     * @param observer
     */
    public void remove(Observer observer){
        observers.remove(observer);
    }

    /**
     * 通知观察者方法
     */
    public abstract void notifyObserver();
}

/**
 * 具体目标(具体被观察者)
 */
class ConcreteSubject extends Subject{
    @Override
    public void notifyObserver() {
        System.out.println("具体目标发生改变!");
        System.out.println("----------------");
        for(Observer obs : observers){
            obs.response();
        }
    }
}

public class ObserverSimpleTest {
    public static void main(String[] args){
        Subject subject = new ConcreteSubject();
        Observer observerA = new ConcreteObserverA();
        Observer observerB = new ConcreteObserverB();
        subject.add(observerA);
        subject.add(observerB);
        subject.notifyObserver();
    }
}

6.观察者模式在Spring框架中的应用

观察者模式在Spring框架中的具体实现就是事件模型驱动开发

Spring中观察者模式的四个角色

1.事件(ApplicationEvent)

在这里插入图片描述

ApplicationEvent 是所有事件对象的父类,类似于被观察者要做的被观察的事情

类似于上面通用写法中的: 在这里插入图片描述

用户可以通过继承ApplicationEvent,实现自定义事件。

下列描述了Spring提供的内置事件

ContextRefreshedEvent:Spring容器刷新完成(所有bean都完成创建)的事件;

ContextClosedEvent:关闭Spring容器的时候的事件。

…等

2.事件发布(ApplicationEventPublisher/ApplicationContext)

在这里插入图片描述

ApplicationContext 是 Spring 中的核心容器,通过它的publishEvent()发布事件的通知给观察者(ApplicationListener)监听到(告诉观察者你需要观察哪个事件),因为事件创建好了不知道会不会被观察者观察到,所以会使用它。

3.事件监听(ApplicationListener)

在这里插入图片描述

ApplicationListener 事件监听器,也就是抽象观察者。继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent(),通过这个方法就是在事件执行的时候观察者要做的事情, 用户可以实现ApplicationListener接口进行事件监听(创建具体观察者)

4.事件多播器(ApplicationEventMulticaster)

ApplicationEventMulticaster 用于事件监听器的注册和事件的广播。等同于被观察者中的observers属性,监听器的注册、删除、把 Applicationcontext (被观察者)发布的事件广播给它的ApplicationListener(被观察者)列表(让他们进行链式调用)。

在这里插入图片描述

1.环境搭建
1.1创建配置类ExtConfig
@ComponentScan("com.wxr.ext")
@Configuration
public class ExtConfig {
   
 
}
1.2创建MyApplicationListener实现ApplicationListener接口

这就是用户自定义创建的具体观察者类

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
   

    /**
     * 当容器中发布此事件以后,该方法出发
     * 监听ApplicationEvent及下面的子事件
     * 根据ApplicationEvent的继承关系:
     * 例如:
	 *		ContextRefreshedEvent:容器刷新完成(所有bean都完成创建)会发布这个事件
     *      ContextClosedEvent:关闭容器的时候会发布这个事件
     * 步骤: 
     *      1.写一个监听器来监听某个事件(ApplicationEvent及其子类)
     *      2.把监听器加入到容器中
     *      3.只要容器中有相应类型的事件发布,我们就监听到这个事件
     * @param event
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
   
        System.out.println("收到事件:"+event);
    }
}

1.3测试代码和结果
public class IocTest {
   
    @Test
    public void test02(){
   
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(ExtConfig.class);
        //发布事件
        ioc.publishEvent(new ApplicationEvent(new String("我发布的事件")) {
   
        });
        System.out.println("ioc容器创建完成");
        ioc.close();
    }
}

在这里插入图片描述

2.源码分析-ApplicationListener原理

根据三.1的输出结果,我们按照先后顺序从ContextRefreshedEvent,IocTest$1,ContextClosedEvent进行分析

执行步骤:

1.向spring容器中注册事件多播器(ApplicationEventMulticaster)

2.向spring容器中注册事件监听器(ApplicationListener)

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值