广告
返回顶部
首页 > 资讯 > 后端开发 > Python >深入理解Java设计模式之观察者模式
  • 751
分享到

深入理解Java设计模式之观察者模式

2024-04-02 19:04:59 751人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录一、什么是观察者模式二、观察者模式的结构三、观察者模式的使用场景使用观察者模式也有两个重点问题要解决:广播链的问题。异步处理问题。四、观察者模式的优缺点五、观察者模式的实现六、观

一、什么是观察者模式

在许多设计中,经常涉及多个对象都对一个特殊对象中的数据变化感兴趣,而且这多个对象都希望跟踪那个特殊对象中的数据变化,也就是说当对象间存在一对多关系时,在这样的情况下就可以使用观察者模式。当一个对象被修改时,则会自动通知它的依赖对象。

观察者模式是关于多个对象想知道一个对象中数据变化情况的一种成熟的模式。观察者模式中有一个称作“主题”的对象和若干个称作“观察者”的对象,“主题”和“观察者”间是一种一对多的依赖关系,当“主题”的状态发生变化时,所有“观察者”都得到通知。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

二、观察者模式的结构

观察者模式的结构中包含四种角色:

(1)主题(Subject):主题是一个接口,该接口规定了具体主题需要实现的方法,比如,添加、删除观察者以及通知观察者更新数据的方法。

(2)观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更新数据的方法。

(3)具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。具体主题需使用一个集合,比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者。

(4)具体观察者(ConcreteObserver):具体观察者是实现观察者接口类的一个实例。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为它的观察者,或让这个具体主题将自己从具体主题的集合中删除,使自己不再是它的观察者。

三、观察者模式的使用场景

(1)当一个对象的数据更新时需要通知其他对象,但这个对象又不希望和被通知的那些对象形成紧耦合。

(2)当一个对象的数据更新时,这个对象需要让其他对象也各自更新自己的数据,但这个对象不知道具体有多少对象需要更新数据。

观察者模式在实际项目的应用中非常常见,比如你到 ATM 机器上取钱,多次输错密码,卡就会被 ATM吞掉,吞卡动作发生的时候,会触发哪些事件呢?第一摄像头连续快拍,第二,通知监控系统,吞卡发生;第三,初始化 ATM 机屏幕,返回最初状态,你不能因为就吞了一张卡,整个 ATM 都不能用了吧,一般前两个动作都是通过观察者模式来完成的。观察者可以实现消息的广播,一个消息可以触发多个事件,这是观察者模式非常重要的功能。

使用观察者模式也有两个重点问题要解决:

广播链的问题。

如果你做过数据库的触发器,你就应该知道有一个触发器链的问题,比如表 A 上写了一个触发器,内容是一个字段更新后更新表 B 的一条数据,而表 B 上也有个触发器,要更新表 C,表 C 也有触发器…,完蛋了,这个数据库基本上就毁掉了!我们的观察者模式也是一样的问题,一个观察者可以有双重身份,即使观察者,也是被观察者,这没什么问题呀,但是链一旦建立,这个逻辑就比较复杂,可维护性非常差,根据经验建议,在一个观察者模式中最多出现一个对象既是观察者也是被观察者,也就是说消息最多转发一次(传递两次),这还是比较好控制的;

异步处理问题。

被观察者发生动作了,观察者要做出回应,如果观察者比较多,而且处理时间比较长怎么办?那就用异步呗,异步处理就要考虑线程安全和队列的问题,这个大家有时间看看 Message Queue,就会有更深的了解。

四、观察者模式的优缺点

优点:

1、具体主题和具体观察者是松耦合关系。由于主题接口仅仅依赖于观察者接口,因此具体主题只是知道它的观察者是实现观察者接口的某个类的实例,但不需要知道具体是哪个类。同样,由于观察者仅仅依赖于主题接口,因此具体观察者只是知道它依赖的主题是实现主题接口的某个类的实例,但不需要知道具体是哪个类。

2、观察者模式满足“开-闭原则”。主题接口仅仅依赖于观察者接口,这样,就可以让创建具体主题的类也仅仅是依赖于观察者接口,因此,如果增加新的实现观察者接口的类,不必修改创建具体主题的类的代码。。同样,创建具体观察者的类仅仅依赖于主题接口,如果增加新的实现主题接口的类,也不必修改创建具体观察者类的代码。

缺点:

1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

五、观察者模式的实现

Observer类---抽象观察者,为所有具体观察者定义一个接口,在得到主题通知时更新自己。

这个接口叫做更新接口,抽象观察者一般用一个抽象类或者一个接口实现。更新接口通常包括一个Update方法,这个方法叫做更新方法。


abstract class Observer
{
    public abstract void Update();
}

Subject类---主题或者抽象通知者,一般用一个抽象类或者一个接口实现。

它把所有对观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者。


abstract class Subject
{
    private List<Observer> observers = new List<Observer>();
    //增加观察者
    public void Attach(Observer observer)
    {
        observers.Add(observer);
    }
    //移除观察者
    public void Detach(Observer observer)
    {
        observers.Remove(observer);
    }
    //通知
    public void Notify()
    {
        foreach (var item in observers)
        {
            item.Update();
        }
    }
}

ConcreteSubject类---具体主题或者具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发送通知。

具体主题角色通常用一个具体类实现。


class ConcreteSubject : Subject
{
    private string subjectState;
    //具体被观察者状态
    public string SubjectState
    {
        get { return subjectState; }
        set { subjectState = value; }
    }
}

ConcreteObserver类---具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。

具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体类实现。


class ConcreteObserver : Observer
{
    private string name;
    private string observerState;
    private ConcreteSubject subject;
     public ConcreteObserver(ConcreteSubject subject, string name)
    {
        this.subject = subject;
        this.name = name;
    }
    public override void Update()
    {
        observerState = subject.SubjectState;
        Console.WriteLine("观察者{0}的新状态是{1}", name, observerState);
    }
    public ConcreteSubject Subject
    {
        get { return subject; }
        set { subject = value; }
    }
}

客户端代码


static void Main(string[] args)
{
    ConcreteSubject cs = new ConcreteSubject();
     cs.Attach(new ConcreteObserver(cs, "X"));
    cs.Attach(new ConcreteObserver(cs, "Y"));
    cs.Attach(new ConcreteObserver(cs, "Z"));
     cs.SubjectState = "ABC";
    cs.Notify();
     Console.Read();
}

结果

观察者X的新状态是ABC
观察者Y的新状态是ABC
观察者Z的新状态是ABC

六、观察者模式和委托的结合

上述代码尽管已经用了依赖倒转原则,但是“抽象通知者”还是依赖“抽象观察者”,也就是说,万一没有了抽象观察者这样的接口,这个通知功能就发送不了。

另外就是每个具体观察者,它不一定是Update的方法调用。

目的:通知者和观察者之间根本就互相不知道,由客户端来决定通知谁


//通知者接口
interface Subject
{
    void Notify();
    string SubjectState { get; set; }
}

具体观察者类


//看股票的同事
class StockObserver
{
    private string name;
    private Subject sub;
     public StockObserver(string name, Subject sub)
    {
        this.sub = sub;
        this.name = name;
    }
    //关闭股票
    public void CloseStock()
    {
        Console.WriteLine("{0}{1}关闭股票,继续工作", sub.SubjectState, sub);
    }
}
//看NBA的同事
class NBAObserver
{
    private string name;
    private Subject sub;
     public NBAObserver(string name, Subject sub)
    {
        this.sub = sub;
        this.name = name;
    }
    //关闭NBA
    public void CloseNBA()
    {
        Console.WriteLine("{0}{1}关闭NBA,继续工作", sub.SubjectState, sub);
    }
}

声明一个委托,无参数,无返回值


//声明一个委托,无参数,无返回值
delegate void EventHandler();

主题或者抽象通知者


//老板类
class Boss : Subject
{
    private string action;
    //声明委托事件Update
    public event EventHandler Update;
     public string SubjectState
    {
        get { return action; }
         set { action = value; }
    }
     public void Notify()
    {
        //在访问通知时,调用Update
        Update();
    }
}
//秘书类
class Secretary : Subject
{
    //与老板类类似,省略......
}

客户端代码


static void Main(string[] args)
{
    //老板张
    Boss Zhang = new Boss();
     StockObserver tongshi1 = new StockObserver("张三",Zhang);
    NBAObserver tongshi2 = new NBAObserver("李四",Zhang);
     Zhang.Update += new EventHandler(tongshi1.CloseStock);
    Zhang.Update += new EventHandler(tongshi2.CloseNBA);
     Zhang.SubjectState = "老板张驾到!";
    Zhang.Notify();
    Console.Read();
}

结果


老板张驾到!张三关闭股票,继续工作
老板张驾到!李四关闭NBA,继续工作

七、总结

实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

另外Redis里的pub/sub也可以实现观察者模式。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: 深入理解Java设计模式之观察者模式

本文链接: https://www.lsjlt.com/news/156630.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 深入理解Java设计模式之观察者模式
    目录一、什么是观察者模式二、观察者模式的结构三、观察者模式的使用场景使用观察者模式也有两个重点问题要解决:广播链的问题。异步处理问题。四、观察者模式的优缺点五、观察者模式的实现六、观...
    99+
    2022-11-12
  • Java设计模式之观察者模式
    目录一、观察者模式的定义和特点二、观察者模式的结构三、代码实例代码示例总结 一、观察者模式的定义和特点 观察者模式的定义: 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改...
    99+
    2022-11-12
  • Java设计模式之java观察者模式详解
    目录引言介绍角色原理类图微信订阅号的案例总结优点缺点适用场景观察者模式的典型应用JDK 提供的观察者接口Guava EventBus 中的观察者模式Spring Applicatio...
    99+
    2022-11-12
  • Java设计模式之观察者模式(Observer模式)
    目录一、观察者模式是什么?二、模式分析2.1 四个角色2.2 案例三、观察者模式的优缺点四、总结一、观察者模式是什么? 当对象间存在一对多关系时,则使用观察者模式(Observer ...
    99+
    2022-11-12
  • Java设计模式探究之观察者模式详解
    目录1.观察者模式是什么2.如何实现3.代码实现1)观察者接口2)被观察者接口3)观察者实现4)被观察者实现5)测试类4.延伸拓展1.观察者模式是什么 顾名思义,有两个对象,观察者和...
    99+
    2022-11-13
  • Java观察者模式的深入了解
    目录一、观察者模式的定义和特点二、观察者模式的结构三、代码实例代码示例总结一、观察者模式的定义和特点 观察者模式的定义: 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时...
    99+
    2022-11-12
  • 深入理解Java设计模式之外观模式
    目录一、什么是外观模式二、外观模式的使用场景三、外观模式的优缺点四、外观模式的实现总结一、什么是外观模式 定义:为子系统中的一组接口提供一个一致的界面,用来访问子系统中的一群接口。 ...
    99+
    2022-11-12
  • 怎么理解Java设计模式的观察者模式
    本篇内容介绍了“怎么理解Java设计模式的观察者模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、什么是观察者模式在许多设计中,经常涉及...
    99+
    2023-06-25
  • Java设计模式中的观察者模式
    目录一.介绍二.场景约束三.UML类图四.示意代码(版本一)五.示意代码(版本二)六.观察者模式与发布订阅模式七.优点八.在JDK中的典型应用一.介绍 观察者模式(Observer ...
    99+
    2023-02-16
    Java观察者模式 Java设计模式
  • 设计模式-观察者模式(Observer)
    讲故事(user story) 假设我们是一个优惠券提供平台,故事就发生在顾客在我们平台采购完成支付成功后。 支付完成后平台要进行的一些操作: 短信通知客户已经生成订单 增加顾客的积分 开始按订单需求制券 ​ ...
    99+
    2018-06-15
    设计模式-观察者模式(Observer)
  • PHP设计模式(观察者模式)
    PHP 设计模式之观察者模式 介绍 现在有两派,有的人建议使用设计模式,有的人不建议使用设计模式! 这就向写文章一样,有的人喜欢文章按照套路走,比如叙事性质的文章,时间,地点,人物,...
    99+
    2022-11-12
  • PHP设计模式之观察者模式浅析
    目录PHP观察者模式(Observer Pattern)模式结构实现步骤代码示例适用场景PHP观察者模式(Observer Pattern) 观察者模式是一种行为设计模式,它定义了一...
    99+
    2023-05-14
    PHP观察者模式 PHP 设计模式 观察者模式
  • Java中常用的设计模式之观察者模式详解
    目录优点缺点使用场景注意事项一、实现方式1、观察者抽象类2、第一个观察者3、第二个观察者4、第三个观察者5、定义主题二、测试总结优点 1.观察者和被观察者是抽象耦合的。 2.建立一套...
    99+
    2022-11-13
  • python面试题——设计模式之观察者模式
    1、观察者模式 观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 观察者模式又称:"发布-订阅"模式。 比如,微信公众号,就是一种...
    99+
    2023-09-12
    python 设计模式 观察者模式
  • PHP设计模式中观察者模式详解
    目录简介适用场景缺点补充代码(自定义实现)简介 观察者模式是行为型模式的一种,定义了对象间一对多的关系。当对象的状态发生变化时候,依赖于它的对象会得到通知。 适用场景 类似触发钩子事...
    99+
    2022-12-20
    PHP观察者模式 PHP设计模式
  • PHP设计模式中观察者模式讲解
    目录简介适用场景优点缺点补充代码(自定义实现)代码(基于SPL实现)简介 观察者模式是行为型模式的一种,定义了对象间一对多的关系。当对象的状态发生变化时候,依赖于它的对象会得到通知。...
    99+
    2022-11-13
    PHP观察者模式 PHP设计模式
  • 深入理解Java设计模式之访问者模式
    目录一、什么是访问者模式二、访问者模式的结构三、访问者模式的使用场景四、访问者模式的优缺点五、访问者模式的实现总结一、什么是访问者模式 定义:表示一个作用于其对象结构中的各元素的操作...
    99+
    2022-11-12
  • 深入理解Java设计模式之中介者模式
    目录一、什么是中介者模式二、中介者模式的结构三、中介者模式的优缺点四、中介者模式的使用场景五、中介者模式与发布/订阅模式的异同六、中介者模式的实现结果总结一、什么是中介者模式 用一个...
    99+
    2022-11-12
  • 深入理解Java设计模式之建造者模式
    目录一、什么是建造者模式二、建造者模式的应用场景三、建造者模式的优缺点四、工厂模式和建造者模式的对比五、建造者模式的实现六、总结一、什么是建造者模式 建造者模式也称生成器模式 定义:...
    99+
    2022-11-12
  • Java通俗易懂系列设计模式之观察者模式
    目录介绍观察者模式Java示例Java观察者模式类图适用场景介绍 观察者模式是行为设计模式之一。当您对对象的状态感兴趣并希望在有任何更改时收到通知时,观察者设计模式非常有用。在观察者...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作