观察者模式

简介: 观察者模式

什么是观察者模式



观察者一般可以看做是第三者,比如在学校上自习的时候,大家肯定都有过交头接耳、各种玩耍的经历,这时总会有一个“放风”的小伙伴,当老师即将出现时及时“通知”大家老师来了。再比如,拍卖会的时候,大家相互叫价,拍卖师会观察最高标价,然后通知给其它竞价者竞价,这就是一个观察者模式。


  对于观察者模式而言,肯定有观察者和被观察者之分。比如在一个目录下建立一个文件,这时系统会通知目录管理器增加目录,并通知磁盘减少空间,在这里,文件就是观察者,目录管理器和磁盘就是被观察者。


  观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。UML结构图如下:


image.png

13931e0b5e88e1dfb6961f3dc62e1d9.png


其中,Subject类是主题,它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供了一个接口,可以增加和删除观察者对象;Observer类是抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己;ConcreteSubject类是具体主题,将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知;ConcreteObserver是具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同。


主题Subject


首先定义一个观察者数组,并实现增、删及通知操作。它的职责很简单,就是定义谁能观察,谁不能观察,用CopyOnWriteArrayList是线程同步的,比较安全,也可以使用ArrayList,是线程异步的,但不安全。

public class Subject {
    //观察者数组
    private CopyOnWriteArrayList<Observer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
    //增加一个观察者
    public void addObserver(Observer observer) {
        this.copyOnWriteArrayList.add(observer);
    }
    //删除一个观察者
    public void deleteObserver(Observer observer) {
        this.copyOnWriteArrayList.remove(observer);
    }
    //通知所有观察者
    public void notifyObserver() {
        copyOnWriteArrayList.forEach(item -> {
            item.update();
        });
    }
}


抽象观察者



观察者一般是一个接口,每一个实现该接口的实现类都是具体观察者。

public interface Observer {
    //更新
    void update();
}


具体主题



继承Subject类,在这里实现具体业务,在具体项目中,该类会有很多变种

public class ConcreteSubject extends Subject {
    //具体业务
    public void doSomething(){
        //...
        super.notifyObserver();
    }
}


具体观察者


public class ConcreteObserver implements Observer{
    @Override
    public void update() {
        System.out.println("收到消息,进行处理");
    }
}
//客户端
public class Client {
    public static void main(String[] args) {
        //创建一个主题
        ConcreteSubject subject = new ConcreteSubject();
        //定义一个观察者
        Observer observer=new ConcreteObserver();
        //观察
        subject.addObserver(observer);
        subject.doSomething();
    }
}


观察者模式的实现



下面举一个具体实例,假设上班时间有一部分同事在看股票,一部分同事在看NBA,这时老板回来了,前台通知了部分同事老板回来了,这些同事及时关闭了网页没被发现,而没被通知到的同事被抓了个现行,被老板亲自“通知”关闭网页,UML图如下:


image.png

image.png


通知者接口


public interface SubjectDemo {
    //增加
    void attach(ObserverDemo observerDemo);
    //删除
    void detach(ObserverDemo observerDemo);
    //通知
    void notifyObservers();
    //状态
    void setAction(String action);
    String getAction();
}


观察者接口


public abstract class ObserverDemo {
    protected String name;
    protected SubjectDemo subjectDemo;
    public ObserverDemo(String name, SubjectDemo subjectDemo) {
        this.name = name;
        this.subjectDemo = subjectDemo;
    }
    public abstract void update();
}


具体通知者


前台Secretary和老板Boss作为具体通知者,实现Subject接口。这里只给出Secretary类的代码,Boss类与之类似。

public class Secretary implements SubjectDemo {
    //同事列表
    private List<ObserverDemo> observerDemos = new CopyOnWriteArrayList<>();
    private String action;
    @Override
    public void attach(ObserverDemo observerDemo) {
        observerDemos.add(observerDemo);
    }
    @Override
    public void detach(ObserverDemo observerDemo) {
        observerDemos.remove(observerDemo);
    }
    @Override
    public void notifyObservers() {
        observerDemos.forEach(item -> {
            item.update();
        });
    }
    @Override
    public void setAction(String action) {
        this.action = action;
    }
    @Override
    public String getAction() {
        return action;
    }
}


具体观察者


public class StockObserver extends ObserverDemo {
    public StockObserver(String name, SubjectDemo subjectDemo) {
        super(name, subjectDemo);
    }
    @Override
    public void update() {
        System.out.println(subjectDemo.getAction()+"\n"+name+"关闭股票行情,继续工作");
    }
}
public class NBAObserver extends ObserverDemo {
    public NBAObserver(String action, SubjectDemo subjectDemo) {
        super(action, subjectDemo);
    }
        @Override
        public void update () {
            System.out.println(subjectDemo.getAction() + "\n" + name + "关闭直播,继续工作");
        }
    }


前台作为通知者进行通知


前台作为通知者,通知观察者。这里添加adam和tom到通知列表,并从通知列表中删除了adam,测试没在通知列表中的对象不会收到通知。

public class TestDemo {
    public static void main(String[] args) {
        //前台为通知者
        Secretary secretary = new Secretary();
        StockObserver observer = new StockObserver("adam", secretary);
        NBAObserver observer1 = new NBAObserver("tom", secretary);
        //前台通知
        secretary.attach(observer);
        secretary.attach(observer1);
        //adam没有被前台通知到,所以被老板抓个现行
        secretary.detach(observer);
        //老板回来了
        secretary.setAction("小心!Boss回来了!");
        //发通知
        secretary.notifyObservers();
    }
}



相关文章
|
存储 算法 C语言
高精度算法
本文详细介绍了高精度算法的实现,涵盖加法、减法、乘法、除法及取模等操作。通过字符串与数组结合的方式,解决了大数运算中超出数据类型范围的问题。每种运算均提供完整的C++代码示例,包括输入处理、位运算模拟、进位/借位逻辑以及结果输出。其中,高精度加法和减法通过逆序存储数字简化计算;乘法利用双重循环模拟手算过程;除法分为低精度和高精度两种情况,分别采用逐位试商与减法模拟;取模则通过逐位累加求余实现。这些方法为处理大规模数值运算提供了有效工具,适用于竞赛编程与实际开发场景。
507 24
|
运维 算法 Ubuntu
Copilot测评报告——2025如果你需要做运维,强烈推荐你使用Copilot
作为一名开发工程师,我曾参与阿里云Copilot的测评工作。2025年最新版Copilot支持Alinux、CentOS、Ubuntu、Anolis OS等操作系统,并新增了Agent模式,可直接执行命令并返回系统健康度等信息,大幅提升了运维效率。它还具备复杂任务理解能力,能处理定时任务和脚本编写,结合管道符号使用,极大便利了运维工作。强烈推荐给中高级运维工程师使用。
887 22
|
存储 人工智能 API
AppAgentX:告别重复点击!自我进化式GUI代理自动生成高级操作,效率翻倍
AppAgentX 是西湖大学推出的新型自我进化式 GUI 代理框架,通过记忆和进化机制提升智能手机交互的效率和智能性,支持复杂任务和跨应用操作,显著优于现有方法。
830 0
|
存储 人工智能 安全
《数据主权:人工智能时代的核心基石与挑战》
在数字化时代,人工智能成为社会变革的强大力量,深刻改变着我们的生活方式。数据主权作为其核心基石,涉及国家、企业和个人的数据管辖与控制权。国家层面,数据主权关乎国家安全与经济竞争力;企业层面,合规利用数据可提升竞争力,但也面临法律风险;个人层面,隐私保护至关重要。国际社会正通过法规和技术手段(如GDPR和区块链)应对这些挑战,以确保数据安全与隐私,推动人工智能健康发展。
438 18
|
存储 人工智能 算法
【深度优先搜索篇】走迷宫的魔法:算法如何破解迷宫的神秘密码
【深度优先搜索篇】走迷宫的魔法:算法如何破解迷宫的神秘密码
|
算法 NoSQL Java
微服务架构下的接口限流策略与实践#### 一、
本文旨在探讨微服务架构下,面对高并发请求时如何有效实施接口限流策略,以保障系统稳定性和服务质量。不同于传统的摘要概述,本文将从实际应用场景出发,深入剖析几种主流的限流算法(如令牌桶、漏桶及固定窗口计数器等),通过对比分析它们的优缺点,并结合具体案例,展示如何在Spring Cloud Gateway中集成自定义限流方案,实现动态限流规则调整,为读者提供一套可落地的实践指南。 #### 二、
469 3
|
安全 Java
Java 泛型上限和下限
Java 泛型上限和下限
|
监控 算法 自动驾驶
计算机视觉的实践与挑战:技术深度剖析
【8月更文挑战第21天】计算机视觉技术作为人工智能的璀璨明珠,正逐步深入到我们生活的各个方面,带来前所未有的便利和变革。然而,随着技术的不断发展,我们也面临着诸多挑战和问题。未来,我们需要不断推动技术创新和跨学科合作,加强数据安全和隐私保护,提升算法的鲁棒性和可解释性,以应对这些挑战并推动计算机视觉技术的持续发展。让我们共同努力,探索计算机视觉技术的广阔天地,为创造一个更加智能、安全和美好的世界而不懈努力。
|
机器学习/深度学习 PyTorch TensorFlow
|
监控 Java 开发者
实现Java微服务架构下的服务熔断与降级
实现Java微服务架构下的服务熔断与降级

热门文章

最新文章