Head First设计模式之观察者模式

简介: 一、定义 观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。 有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。

一、定义

观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。

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

观察者模式是写松耦合代码的必备模式。

 

二、结构

三、实现

//被观察者
 
public interface IObject
    {
 
        IList<IMonitor> ListMonitor { get; set; } //定义观察者集合,因为多个观察者观察一个对象,所以这里用集合
        string SubjectState { get; set; }        //被观察者的状态
     
 
        void AddMonitor(IMonitor monitor);  //添加一个观察者
 
        void RemoveMonitor(IMonitor monitor); //移除一个观察者
 
        void SendMessage(); //向所有观察者发送消息
 
    }
    public class Subject : IObject
    {
 
 
        private IList<IMonitor> listMonitor = new List<IMonitor>();
 
        public string SubjectState //被观察者的状态
        {
            get;set;
        }
 
 
        public IList<IMonitor> ListMonitor //实现具体的观察者列表属性
        {
            get { return listMonitor; }
            set { listMonitor = value; }
        }
 
        public void AddMonitor(IMonitor monitor)  //实现具体的添加观察者方法
        {
            listMonitor.Add(monitor);
        
        }
 
        public void RemoveMonitor(IMonitor monitor) //实现具体的移除观察者方法
        {
           
            listMonitor.Remove(monitor);
        }
 
        public void SendMessage()    //实现具体的发送消息方法
        {
            foreach (IMonitor m in listMonitor)  //发送给所有添加过的观察者,让观察者执行update方法以同步更新自身状态
            {
                m.Update();
            }
        }
    }
 
 
//观察者
 
  public interface IMonitor //定义观察者接口
    {
        void Update(); 
    }
 
 
    public class Monitor : IMonitor   //实现具体观察者
    {
        private string monitorState="Stop!";    //观察者初始状态,会随着被观察者变化而变化
        private string name;            //观察者名称,用于标记不同观察者
        private IObject subject;        //被观察者对象
 
 
 
        public Monitor (IObject subject, string name)  //在构造观察者时,传入被观察者对象,以及标识该观察者名称
        {
            this.subject = subject;
            this.name = name;
            Console.WriteLine("我是观察者{0},我的初始状态是{1}", name, monitorState);
 
 
        }
 
 
        public void Update()                           //当被观察者状态改变,观察者需要随之改变
        {
            monitorState = subject.SubjectState;
            Console.WriteLine("我是观察者{0},我的状态是{1}", name, monitorState);
 
        }
    }
 
 
//前端调用
 
   static void Main(string[] args)
        {
 
            IObject subject = new Subject();
            subject.AddMonitor(new Monitor(subject, "Monitor_1"));
            subject.AddMonitor(new Monitor(subject, "Monitor_2"));
            subject.AddMonitor(new Monitor(subject, "Monitor_3"));
 
            subject.SubjectState = "Start!";
            subject.SendMessage();
 
            Console.Read();
        }
    }

 

四、适用场景

1 当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。

2 一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。

 

五、优缺点

  优点

    观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。

  缺点

    依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。

六、模式引申

  应用C#中的事件委托来彻底解除通知者和观察者之间的耦合。

  1 关于委托的定义:委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法有相同的行为。委托方法可以像其它任何方法一样,具有参数和返回值。委托可以看作是对函数(方法)的的抽象,是函数的“类”,委托的实例代表一个(或多个)具体的函数,它可以是多播的。

  2 关于事件:事件基于委托,为委托提供了一种发布/订阅机制。事件的订阅与取消与我们刚才讲的观察者模式中的订阅与取消类似,只是表现形式有所不同。在观察者模式中,订阅使用方法Attach()来进行;在事件的订阅中使用“+=”。类似地,取消订阅在观察者模式中用Dettach(),而事件的取消用“-=”。

 

七、答疑

1. 在普通的观察者模式中,解耦并不彻底,那么在事件的发布订阅模型中,解耦彻底吗?为什么?

答案是肯定的。因为在事件中,订阅者和发布者之间是通过把事件处理程序绑定到委托,并不是把自身传给对方。所以解决了观察者模式中不完全解耦的问题。这也是关键点之四

2. 通过委托绑定方法来实现观察者模式,会不会有什么隐患?

有的,通过+=去把方法绑定到委托,很容易忘记-=。如果只绑定不移除,这个方法会一直被引用。我们知道GC去回收的时候,只会处理没有被引用的对象,只要是还被引用的对象时不会被回收掉的。所以如果在长期不关闭的系统中(比如监控系统),大量的代码使用+=而不-=,运行时间长以后有可能会内存溢出。

3. 事件,委托,观察者模式之间的关系

这个上面已经提到了,委托时一种类型,事件是一种特殊的委托,观察者模式是一种设计模式,事件的机制是观察者模式的一种实现,其中订阅者和发布者通过委托实现协同工作。

好的,最后我们还是来归纳一下观察者模式的关键点

一、每个观察者需要被保存到被观察者的集合中,并且被观察者提供添加和删除的方式。

二、被观察者把自己传给观察者,当状态改变后,通过遍历或循环的方式逐个通知列表中的观察者。

三、虽然解耦了观察者和被观察者的依赖,让各自的变化不大影响另一方的变化,但是这种解耦并不是很彻底,没有完全解除两者之间的耦合。

四、在事件中,订阅者和发布者之间是通过把事件处理程序绑定到委托,并不是把自身传给对方。所以解决了观察者模式中不完全解耦的问题

注意点:在使用委托绑定方法时,需要注意移除方法,否则可能会造成内存溢出。

建议:不能理解事件和委托的同学,好好地把事件和委托看一看,并且自己写点代码加深印象。

 

参考:

http://blog.jobbole.com/109845/

http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html

 

欢迎阅读本系列文章:Head First设计模式之目录

 

相关文章
|
3月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
24天前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
199 8
|
11月前
|
设计模式 存储 供应链
前端必须掌握的设计模式——观察者模式
观察者模式(Observer Pattern)是一种行为型设计模式,实现了一种订阅机制。它包含两个角色:**观察者**(订阅消息、接收通知并执行操作)和**被观察者**(维护观察者列表、发送通知)。两者通过一对多的关系实现解耦,当被观察者状态改变时,会通知所有订阅的观察者。例如,商店老板作为被观察者,记录客户的需求并在商品到货时通知他们。前端应用中,如DOM事件注册、MutationObserver等也体现了这一模式。
|
6月前
|
设计模式 消息中间件 存储
【设计模式】【行为型模式】观察者模式(Observer)
一、入门 什么是观察者模式? 观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会收到通知并自动更新。
332 9
|
8月前
|
设计模式 消息中间件 存储
设计模式:观察者模式
观察者模式属于行为型设计模式,用于建立对象间的一对多依赖关系。当主题(Subject)状态变化时,所有依赖的观察者(Observer)会自动收到通知并更新。
|
12月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
198 6
|
12月前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
103 1
|
6月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
189 16
|
6月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
192 0
|
6月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
174 0

热门文章

最新文章