设计模式之观察者模式 (Observer Design Pattern)_观察者模式例子 嵌入式-程序员宅基地

技术标签: 观察者模式  Observer  设计模式  

一、什么是观察者模式

观察者定义了一种一对多的依赖关系,当一个主题(Subject)对象状态发生变化时,所有依赖它的相关对象都会得到通知并且能够自动更新自己的状态,这些依赖的对象称之为观察者(Observer)对象这类似于发布/订阅模式。

观察者模式中的主题对象,会维持着一个依赖它的观察者对象列表,当主题对象状态发生改变时,主题对象便会调用这个列表中所有观察者对象的方法。

观察者模式一般用在分布式时间处理系统,它也是流行的MVC模型的核心设计模式。

二、观察者模式中的角色

观察者模式主要涉及到三个组件:Subject、Observer、ConcreteObserver

  • 主题(Subject):保存了所有观察者的引用,并供注册、删除观察者的接口,提供自己状态变化触发所有观察者更新的方法
  • 观察者(Observer):定义了更新自己状态的接口
  • 具体观察者( ConcreteObserver):具体实现观察者接口,使自己的状态和主题状态一致

这里写图片描述

三、代码实例

1. 主题对象类

import java.util.ArrayList;
import java.util.List;
public class Subject {
    
    //主题对象维持着一个依赖它的观察者对象列表
    private List<Observer> observers = new ArrayList<Observer>();
    //主题对象的状态
    private int state;
    //当主题对象状态变化时,调用所有观察者对象的方法
    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }
    //调用所有依赖它的观察者的方法
    public void notifyAllObservers(){
        for (Observer observer : observers) {
            observer.update(state);
        }
    }
    //主题对象也可以注册、和删除依赖它的观察者对象
    public void attach(Observer observer){
        observers.add(observer);
    }

    public int getState() {
        return state;
    }
}

2. 观察者接口

public abstract class Observer {
    public abstract void update(int state);
}

3. 具体的观察者

public class ConcreteObserverA extends Observer{
    

    @Override
    public void update(int state) {
        System.out.println( "ConcreteObserverA get state change event: " + state );
    }
}
public class ConcreteObserverB extends Observer{
    

    @Override
    public void update(int state) {
        System.out.println( "ConcreteObserverA get state change event: " + state );
    }
}

最后写一个测试类测试一下

public class ObserverPatternDemo {
    public static void main(String[] args) {
        //初始化主题对象
        Subject subject = new Subject();
        //注册观察者对象到主题对象
        ConcreteObserverA ConcreteObserverA=new ConcreteObserverA();
        ConcreteObserverB ConcreteObserverB=new ConcreteObserverB();
        subject.attach(ConcreteObserverA);
        subject.attach(ConcreteObserverB);
        //主题对象状态发生变化
        subject.setState(20);

    }
}

我们看一下运行结果:

ConcreteObserverA get state change event: 20
ConcreteObserverA get state change event: 20

当主题对象状态发生改变,两个注册的观察者都收到了通知。

四、总结

其实观察者模式很简单,其核心内涵依然是用面向对象思想思考问题而非面向过程思想,面向接口编程,解耦合依赖。

但是观察者模式也有缺点,观察者模式是一种常用的链式触发机制,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/suifeng3051/article/details/51263718

智能推荐

webHttpBinding、basicHttpBinding和wsHttpBinding区别_basichttpbinding与wshttpbinding与webhttpbinding-程序员宅基地

文章浏览阅读1.1k次。webHttpBinding与basicHttpBinding / wsHttpBinding的区别_basichttpbinding与wshttpbinding与webhttpbinding

linux dmesg路径,Linux命令——dmesg-程序员宅基地

文章浏览阅读251次。前言Linux启动是个复杂的流程,BIOS->MBR->boot loader。。。boot loader阶段有Kernel以及initrd,Kernel通过initrd加载到bootable device的驱动后正式接管根目录文件系统,然后加载各种驱动,准备OS下程序运行环境等等。boot loader详细工作如下图。Kernel做了这么多事情,有什么办法观察内核所作的工作吗? d..._dmesg 路径

python requests get请求 超时_尝试在python中执行get请求时获取[Errno 110]“连接超时”...-程序员宅基地

文章浏览阅读1.4k次。我可以在firefox浏览器中手动访问下面代码中提到的“URL”,并看到json响应如下:{"version" : "1.0","email_address" : "[email protected]"}但是当我试图用下面的代码获取请求时,我得到的是连接超时错误。import requestsURL='https://deviceconfig.pod1.pie.avatar.ext.hp.com/v..._python requests [errno 110] connection timed out

凑硬币算法C语言,《凑硬币》 动态规划算法入门-程序员宅基地

文章浏览阅读571次。题目描述如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?思路问题动态规划算法的核心是:每个子问题的状态和状态的转移方程。状态是:dp[i] ,即凑够i元最少需要的硬币的个数转移方程是:dp[i] = min(dp[i-C1]+1,dp[i-C2]+1,dp[i-C3]+1,……,dp[i-Cj]+1])即,每个状态的值都是最小的那个。编写代码说明:通过递归函数dp_fun..._10元最多构成几枚硬币 动态规划

python自动化运维-Python自动化运维学习资源汇总-程序员宅基地

文章浏览阅读449次。运维工种对于自动化的强烈需求已经显漏无疑——作为一个古老的技术工种,在几台、几十台服务器时尚可人肉维护,面对云计算时代动辄上百上千的服务器,单凭人肉维护显然束手无策。想像一下诸如谷歌、阿里云的上万台服务器,如果单凭人工维护恐怕运维就会成为人员需求量最高的工种,没有之一。在Devops备受推崇的时代,即使开发也难免要接触到一些运维工作。所以今天为大家整理了一些自动化运维的学习资源,希望能够给大家提供..._《python 自动化运维》(python for devops)

STM32G030F6P6烧录程序无法启动运行-程序员宅基地

文章浏览阅读2k次。原因分析,STM32G030F6P6与STM32F系列的启动特点有一些差异,主要是默认的nBOOT_SEL被设置为1,即由内部BOOT位配置启动,使用官方提供的STM32CubeProgrammer修改不了nBOOT_SEL配置,后来通过命令行执行下列代码后,修改nBOOT_SEL为0,芯片可正常启动。初次使用STM32G030F6P6开发了一款电路板,但是发现烧录程序后无法启动运行的问题。_stm32g030f6p6烧录

随便推点

C++学习之双端队列depue_depuec++-程序员宅基地

文章浏览阅读1.9k次。6、双端队列deque所谓的deque是”double ended queue”的缩写,双端队列不论在尾部或头部插入元素,都十分迅速。而在中间插入元素则会比较费时,因为必须移动中间其他的元素。双端队列是一种随机访问的数据类型,提供了在序列两端快速插入和删除操作的功能,它可以在需要的时候改变自身大小,完成了标准的C++数据结构中队列的所有功能。Vector是单向开口的连续线性空间,deque则..._depuec++

多年大数据开发经验总结_大数据项目经历-程序员宅基地

文章浏览阅读5.5k次,点赞15次,收藏8次。多年工作经验总结初入行,搞大数据开发。得高人指点,先学mapreduce,不足一年,tez兴,后入此道。朝夕不倦,发愤图强,才能略知一二。无奈后浪推前浪,tez被spark拍在沙滩上,遂投spark之怀。继而抖擞精神,奋袂而起,github、stackoverflow轮番上阵,终七窍通六窍。然乾坤更替,岁月不复,spark转眼成过眼烟云,flink、 beam之流成业界新宠,一时洛阳纸贵,众人..._大数据项目经历

Python实现时间序列分析进行平稳性检验(ADF和KPSS)和差分去趋势(adfuller和kpss算法)项目实战_python adf检验-程序员宅基地

文章浏览阅读1.3k次,点赞18次,收藏20次。Python实现时间序列分析进行平稳性检验(ADF和KPSS)和差分去趋势(adfuller和kpss算法)项目实战_python adf检验

Intellij Idea 设置方法模板_idea if模板-程序员宅基地

文章浏览阅读2w次,点赞5次,收藏6次。设置Idea的方法注释模板 详细配置: /** * @author usernameusername datedate * @time timetime * @method methodmethod * @param paramparam * @return methodretur_idea if模板

MATLAB调用OpenCV流程(MATLAB R2016a+OpenCV3.1.0+VS2010)_matlab写的程序会提到opencv吗-程序员宅基地

文章浏览阅读7.2k次,点赞2次,收藏44次。第一次使用MATLAB和C++混编,综合一些网上的教程,最终实现功能,尽管理解不是很深刻,但先记录下来,以后慢慢领悟。在MATLAB命令行窗口中输入命令“mex -setup C++”,此时显示如下图所示: 在MATLAB命令行窗口中输入命令“mbulid -setup C++”,此时显示如下图所示: 此时编译环境搞定,但是得通过配置文件xml,修改前先编写一个测试代码,文件名为OpenC..._matlab写的程序会提到opencv吗

关于网络安全那点事:MYSQL使用教程-程序员宅基地

文章浏览阅读840次,点赞23次,收藏16次。从时代发展的角度看,网络安全的知识是学不完的,而且以后要学的会更多,同学们要摆正心态,既然选择入门网络安全,就不能仅仅只是入门程度而已,能力越强机会才越多。因为入门学习阶段知识点比较杂,所以我讲得比较笼统,大家如果有不懂的地方可以找我咨询,我保证知无不言言无不尽,需要相关资料也可以找我要,我的网盘里一大堆资料都在吃灰呢。干货主要有:①1000+CTF历届题库(主流和经典的应该都有了)②CTF技术文档(最全中文版)③项目源码(四五十个有趣且经典的练手项目及源码)