设计模式-从回调函数入手理解观察者模式

本文参考:

入门对比:Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)_Chen4852010的博客-CSDN博客

参考例子:观察者模式VS监听器模式_观察者模式和监听者模式的区别_岁月玲珑的博客-CSDN博客

阿里社区:Java中的设计模式(一):观察者模式-阿里云开发者社区 (aliyun.com)

一、回调函数

理解了回调函数,也就能更好地理解观察者模式,其很好地利用了回调机制。

回调函数被外部定义实现,由调用方触发,理解为“回头调用定义的函数”。

这里分为两个对象:

  • 调用方
  • 定义方(面向接口编程,以此规范回调函数的定义)。

回调函数Demo:

  1. 定义回调接口

    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public interface ICallBack {
        void callBack();
    }
    
  2. 回调触发者动作

    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public class Caller {
        public void callerFunc(ICallBack f){ // 这里能传入回调定义方的逻辑
            System.out.println("start...");
            // 回调函数
            f.callBack();
            System.out.println("end...");
        }
    }
    
  3. 测试

    import org.junit.Test;
    
    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public class TestCallerFunc {
        @Test
        public void testCallerFunc(){
            Caller caller = new Caller();
            caller.callerFunc(new ICallBack() { // 调用方触发定义方的逻辑
                @Override
                public void callBack() {
                    System.out.println("我是自定义的回调函数...");
                }
            });
        }
    }
    

    输出:

    start...
    我是自定义的回调函数...
    end...
    

其实我们最常见的实现Runnable接口创建线程的方式也是回调函数的实现:Runable接口是回调接口,Thread是调用方触发者

@Test
public void testThread(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("我是自定义的回调函数...");
        }
    }).start();
}

二、观察者模式(发布订阅模式)

观察者模式 (Observer Pattern)是用于建立一种对象和对象之间依赖关系的 对象行为型设计模式 ,其定义为:

在对象之间定义一对多的依赖,当一个对象状态改变时,所有依赖的对象都会自动收到通知。

同样分为两个对象:

  • 观察者(Observer)监听被观察者产生的改变。A用户观察B,则A观察者,B是被观察者。观察者对象不知道其他观察者的存在, 它只知道如何更新自己。

  • 主题对象(被观察者)内部维护了一个观察者列表,并在消息message产生变化时通知notify()所有的观察者,也就是回调观察者列表中每个observer的回调方法,表示观察者做出反应react()(观察者暴露给被主题对象的)。

观察者模式Demo:

  1. 定义主题接口

    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public interface Subject {
        // 注册观察者
        void registerObserver(Observer observer);
        // 移除观察者
        void removeObserver(Observer observer);
    
        // 发布一个消息
        void publishMessage(String message);
        // 核心功能,通知观察者
        void notifyObservers();
    }
    
  2. 具体的主题接口实现类

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public class ConcreteSubject implements Subject{
        // 观察者的列表
        private List<Observer> observerList=new ArrayList<>();
        // 发布的信息
        private String message;
        @Override
        public void registerObserver(Observer observer) {
            observerList.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            observerList.remove(observer);
        }
    
        @Override
        public void publishMessage(String message) {
            this.message=message;
            // 通知所有观察者
            notifyObservers();
        }
    
        @Override
        public void notifyObservers() {
            for(Observer observer:observerList){
            	// 回调观察者的反应接口 
                observer.react(message);
            }
        }
    }
    
  3. 定义观察者接口

    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public interface Observer {
        void react(String message);
    }
    
  4. 具体的观察者接口实现类

    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public class ConcreteObserver implements Observer{
        String name;
        String recvMeesage;
        public ConcreteObserver(String name){
            this.name=name;
        }
    
        @Override
        public void react(String message) {
            this.recvMeesage=message;
            System.out.println("["+name+"]"+" receive message: "+recvMeesage);
        }
    }
    
  5. 测试

    import org.junit.Test;
    
    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/5/21
     */
    public class TestObserver {
        @Test
        public void testObserver(){
            // 创建具体主题对象
            ConcreteSubject concreteSubject = new ConcreteSubject();
            // 创建具体观察者
            ConcreteObserver observer1 = new ConcreteObserver("Observer1");
            ConcreteObserver observer2 = new ConcreteObserver("Observer2");
            // 注册观察者到主题对象
            concreteSubject.registerObserver(observer1);
            concreteSubject.registerObserver(observer2);
    
            // 发布消息Message
            concreteSubject.publishMessage("观察者模式测试消息...");
            // 再提醒一次
            concreteSubject.notifyObservers();
    
            // 移除一个观察者并通知当前新的观察者列表
            concreteSubject.removeObserver(observer1);
            concreteSubject.notifyObservers();
        }
    }
    

    输出:

    [Observer1] receive message: 观察者模式测试消息...
    [Observer2] receive message: 观察者模式测试消息... // publishMessage提醒一次
    [Observer1] receive message: 观察者模式测试消息...
    [Observer2] receive message: 观察者模式测试消息... // 再提醒一次
    [Observer2] receive message: 观察者模式测试消息... // 移除了observer1
    

    在JDK和Spring中也有对此模式的实践,参考Java中的设计模式(一):观察者模式-阿里云开发者社区 (aliyun.com)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基本概念 if you call me, i will call back 什么是回调函数 回调函数(callback Function),顾名思义,用于回调的函数。 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数。回调函数是一个工作流的一部分,由工作流来决定函数的调用(回调)时机。回调函数包含下面几个特性: >属于工作流的一个部分; >必须按照工作流指定的调用约定来申明(定义); >他的调用时机由工作流决定,回调函数的实现者不能直接调用回调函数来实现工作流的功能; 回调机制 回调机制是一种常见的设计模型,他把工作流内的某个功能,按照约定的接口暴露给外部使用者,为外部使用者提供数据,或要求外部使用者提供数据。 java回调机制: 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。 >同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用; >回 调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口; >异步调用:一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。 回调和异步调用的关系非常紧密:使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网民工蒋大钊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值