设计模式-行为模式-观察者模式 以及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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 设计模式是软件开发中常用的一种解决方案,它们是一些经过实践验证的可复用设计思想。设计模式允许开发人员在类和对象的结构上灵活地更改,并提供了一种优雅的解决方案来应对各种软件开发问题。 GOF(Gang of Four)是指Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位软件工程师,他们在《设计模式:可复用面向对象软件的基础》一书中总结了23种常见的设计模式,这本书因此而获得了“设计模式圣经”的称号。 这本书以案例为基础,深入浅出地讲解了每个设计模式的原理和应用场景,并提供了C++实现码。 其中,创建型设计模式包括单例模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式。这些模式都提供了一种方式来创建对象,使得程序在实例化对象时更加灵活和可扩展。 结构型设计模式包括适配器模式、装饰器模式、代理模式、组合模式、享元模式和外观模式。这些模式关注如何通过类和对象的组合来创建更大的结构,并提供了一种优雅的方式来简化系统的复杂性。 行为设计模式包括策略模式、模板方法模式观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式和中介者模式。这些模式关注对象之间的通信和交互,它们提供了一种优雅的方式来实现松耦合和可维护的代码。 总之,设计模式是软件开发中非常重要的一部分,它们提供了一种通用的解决方案来处理常见的设计问题。通过学习和应用设计模式,开发人员可以提高代码的可复用性、可扩展性和可维护性,并加快开发进度。 ### 回答2: 设计模式是软件开发中常用的解决问题的一种思维方式或者说是一种已被证实有效的解决问题的方法。GOF 23种设计模式是由四位著名的软件工程师提出并总结出的一套经典的设计模式。 GOF 23种设计模式分别是创建型模式、结构型模式行为模式。创建型模式包括简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、建造者模式和原型模式。结构型模式包括适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式和代理模式行为模式包括策略模式、模板方法模式观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式和解释器模式。 GOF 23种设计模式具有不同的应用场景和优势。通过学习和理解这些设计模式,开发者可以更加灵活地应对各种软件开发中的问题。同时,掌握这些设计模式也有助于提高代码的可读性、可维护性和可扩展性。 附带C语言实现码是一种更加具体的学习和理解设计模式的方法。通过查看实现码,可以更加直观地看到设计模式在实践中的应用。这些码可以作为学习的参考,帮助开发者更好地理解设计模式的思想和使用方式。 总之,设计模式是软件开发中非常重要的一部分,通过学习GOF 23种设计模式并理解其应用场景和优势,可以提高软件开发的效率和质量。附带C语言实现码能够更加具体地帮助开发者理解设计模式的实际应用。 ### 回答3: 设计模式是软件工程中常用的一种设计思想或模板,可以用于解决特定的问题和提供可重用的解决方案。GOF(Gang of Four)提出了23种设计模式,并在书籍《设计模式:可复用面向对象软件的基础》中进行了详细的解析和说明。 这本书详细地介绍了23种设计模式,包括创建型模式、结构型模式行为模式。通过阅读这本书,读者可以了解每种设计模式的特点、适用场景和实现方法。另外,书中还通过示例代码的方式演示了每种设计模式的具体实现,并提供了附带的C语言实现码。 这本书对于理解设计模式的概念和思想非常有帮助。它不仅提供了23种设计模式的名字和简介,还详细解释了每种模式的适用场景和应用案例。读者可以通过学习这些设计模式,了解如何将它们应用于自己的软件开发工作中,提高代码的可重用性和可维护性。 书中的C语言实现码是帮助读者理解和实践设计模式的重要资。通过阅读码,读者可以更加深入地理解每种设计模式的具体实现细节,并进一步提升自己的编程能力。 总之,通过学习《设计模式:可复用面向对象软件的基础》这本书,读者可以全面了解设计模式的概念、分类和实现方法,并通过阅读附带的C语言实现码来加深对设计模式的理解和应用。这将对提升软件设计和开发的能力和水平非常有帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值