简介

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

定义

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式)定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

类型

行为型模式

类图

图1 类图

结构

最基础的观察者模式包括以下四个角色:

  • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
  • ConcrereObserver:具体观察者,是实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

使用场景

  • 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
  • 事件多级触发场景。
  • 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

优点

  • 观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。
  • 观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。

缺点

在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂 而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

模拟场景

假设有一个软件公司,每当有新产品推出,就把信息通知到一些客户。

实现

C#版

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace Observer
{
class Program
{
static void Main(string[] args)
{
MyCompany company = new MyCompany();
IService customerA = new Customer("Alice");
IService customerB = new Customer("Bob");
company.Subscribe(customerA);
company.Subscribe(customerB);
company.SendMsg();
Console.ReadLine();
}
}
/// <summary>
/// 抽象观察者
/// </summary>
public interface IService
{
void Update();
}
/// <summary>
/// 具体观察者
/// </summary>
public class Customer : IService
{
private string name;
public Customer(string name)
{
this.name = name;
}
public void Update()
{
Console.WriteLine("客户{0}收到通知了", this.name);
}
}
/// <summary>
/// 抽象被观察者
/// </summary>
public interface IMyCompany
{
//合作
void Subscribe(IService subscriber);
//取消合作
void CancelSubscribe(IService subscriber);
//向客户发送更新消息
void SendMsg();
} /// <summary>
/// 被观察者
/// </summary>
public class MyCompany : IMyCompany
{
private IList<IService> subscribers = new List<IService>(); public void Subscribe(IService subscriber)
{
subscribers.Add(subscriber);
}
public void CancelSubscribe(IService subscriber)
{
subscribers.Remove(subscriber);
}
public void SendMsg()
{
foreach (IService service in subscribers)
{
service.Update();
}
}
}
}

Java版

package Observer;
import java.util.ArrayList;
import java.util.List; public class Program {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MyCompany company = new MyCompany();
IService customerA = new Customer("Alice");
IService customerB = new Customer("Bob");
company.Subscribe(customerA);
company.Subscribe(customerB);
company.SendMsg();
}
}
interface IService {
void Update();
}
class Customer implements IService
{
private String name;
public Customer(String name)
{
this.name = name;
}
public void Update()
{
System.out.println("客户"+this.name+"收到通知了");
}
}
/// <summary>
/// 抽象被观察者
/// </summary>
interface IMyCompany
{
//合作
void Subscribe(IService subscriber);
//取消合作
void CancelSubscribe(IService subscriber);
//向客户发送更新消息
void SendMsg();
} /// <summary>
/// 被观察者
/// </summary>
class MyCompany implements IMyCompany
{
private List<IService> subscribers = new ArrayList<IService>();
public void Subscribe(IService subscriber)
{
subscribers.add(subscriber);
}
public void CancelSubscribe(IService subscriber)
{
subscribers.remove(subscriber);
}
public void SendMsg()
{
for (IService service : subscribers)
{
service.Update();
}
}
}

设计模式之观察者模式(Observer)(4)的更多相关文章

  1. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  2. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  3. 人人都会设计模式:观察者模式--Observer

    https://segmentfault.com/a/1190000012295887 观察者模式是抽像通知者和观察者,达到具体通知者跟具体观察者没有偶合.能达到不管是切换通知者,或者是切换观察者,都 ...

  4. 二十四种设计模式:观察者模式(Observer Pattern)

    观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...

  5. [设计模式] 19 观察者模式 Observer Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...

  6. c#设计模式之观察者模式(Observer Pattern)

    场景出发 一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了 这个过程,如果用面向对象语言来描述,简单莫过于下: public class Cat { ...

  7. JAVA设计模式之观察者模式 - Observer

    有趣的事情发生时,可千万别错过了!有一个模式可以帮你的对象知悉现况,不会错过该对象感兴趣的事.对象甚至在运行时可决定是否要继续被通知.有了观察者,你将会消息灵通. 介绍 观察者模式的定义: 在对象之间 ...

  8. 设计模式之观察者模式(Observer pattern)

    最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下: 上课铃声响起,学生A/B/C/D进入教室:下课铃声响起,学生A/B/C/D离开教室. 要求使用设计模式的思想完成铃与学 ...

  9. 设计模式之观察者模式(Observer)

    观察者模式原理:当有新的消息产生时发送给观察者,和中介者模式的不同地方是中介者模式强调中介的作用以及中介双方的交互,观察者模式是主动调用观察者成员函数进行消息发送. 代码如下: #include &l ...

  10. 设计模式九: 观察者模式(Observer Pattern)

    简介 观察者属于行为型模式的一种, 又叫发布-订阅模式. 如果一个对象的状态发生改变,依赖他的对象都将发生变化, 那么这种情况就适合使用观察者模式. 它包含两个术语,主题(Subject),观察者(O ...

随机推荐

  1. 个人网站搭建时linux中的相关配置记录(mysql,jdk,nginx,redis)

    一.开发计划(包括准备工作,网站大致需求等) 二.服务器(linux/centos)购买.相应环境配置(jdk),软件安装(mysql, nginx, redis).域名解析 三.原型图.代码开发(v ...

  2. php5.3新垃圾回收机制详解

    php的垃圾回收机制主要参考了http://blog.csdn.net/phpkernel/article/details/5734743 这文章. 变量对应的值,比如 $a="abc&qu ...

  3. Nuget 打包

    https://github.com/NuGetPackageExplorer/NuGetPackageExplorer 下载地址 1 打包的dll 中没有依赖 最简单的情况,保证dll放到lib下, ...

  4. JobScheduler android任务调度处理组件(类似QuartZ)

    JobScheduler是Android L(API21)新增的特性,用于定义满足某些条件下(电量,网络,时间,屏幕熄/亮 ,设备是否空闲 等)执行的任务.它的宗旨是把一些不是特别紧急的任务放到更合适 ...

  5. 剑指offer十之矩形覆盖

    一.题目 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 二.解答思路 如果第一步选择竖方向填充,则剩下的填充规模缩小 ...

  6. 【从0到1学Web前端】CSS定位问题一(盒模型,浮动,BFC) 分类: HTML+CSS 2015-05-27 22:24 813人阅读 评论(1) 收藏

    引子: 在谈到css定位问题的时候先来看一个小问题: 已知宽度(假如:100px)div框,水平居中,左右两百年的分别使用div框填充.且左右div自适应. 效果如下图: 这个问题的难点主要是浏览器宽 ...

  7. 关于配置 TeamCity 清理历史 artifacts 问题

    使用 CI 一段时间后,artifacts 占用的磁盘会很大,可以配置保留多少天的 artifacts,具体如下: Administration Click the Edit link for any ...

  8. 确保线程安全下使用Queue的Enqueue和Dequeue

    场景是这样,假设有一台设备会触发类型为Alarm的告警信号,并把信号添加到一个Queue结构中,每隔一段时间这个Queue会被遍历检查,其中的每个Alarm都会调用一个相应的处理方法.问题在于,检查机 ...

  9. 微信小程序(wx:for)遍历对象

    最近在折腾微信小程序,遇到这么一个情况:后端返回一个key-value的对象数据,需要遍历对象的key-value,然后渲染到视图中.就像下面这样: { '2018-1-9':{ address: ' ...

  10. 全网最详细的Windows系统里PLSQL Developer 32bit的下载与安装过程(图文详解)

    不多说,直接上干货! 注意的是: 本地若没有安装Oracle服务端,Oracle server服务端32位,是远程连接,因此本地配置PLSQL Developer32位. PLSQL Develope ...