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

本文介绍了回调函数的概念,通过示例展示了如何使用回调函数,并将其与观察者模式进行对比。观察者模式是一种对象行为型设计模式,允许一个对象的状态改变时通知其他依赖它的对象。文章提供了观察者模式的实现示例,包括主题接口、观察者接口以及它们的具体实现,并展示了如何在Java中应用这种模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文参考:

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

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

阿里社区: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)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

互联网民工蒋大钊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值