知识大全 .net设计模式之观察者模式

Posted

篇首语:刀不磨要生锈,人不学要落后。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 .net设计模式之观察者模式相关的知识,希望对你有一定的参考价值。

  故事

     小雪是一个非常漂亮的女孩 漂亮的女孩总是有很多的追求者 而且追求者的队伍在不断的变动 随时有人进入这个队伍 也有人退出 男孩们追求女孩时总是表现出 %的关心 当小雪私自游玩时总是不断收到追求者询问小雪位置变动的消息 小雪也不胜其烦 但小雪是如此的一个善良的女孩 她总是打断自己正常的生活回复男孩们的消息 而男孩们由于要不断的关心小雪的位置变化也弄的精疲力竭 而且还影响正常的工作

  在这样一个简单的故事场景中我们发现了什么?来看看小雪和男孩们的烦恼

  男孩们必须不断的询问小雪的位置变化 从而打断正常的工作

  小雪也要不断的接受男孩们的询问 有的时候小雪的位置并没有发生变化 还是要不断的回复男孩们的询问 也影响正常的工作

  如果给各个男孩们回复问题的方式都不尽相同 小雪还要知道不同的回复方式 而且不断的有新的男孩们增加进来 还不知道未来有什么新的回复方式

  看到这么多烦恼 我们创意无限的Nokia公司给小雪和男孩们提出了解决方案

     Nokia公司荣誉出品了一款带有GPRS功能的手机 该手机保存著一个订阅位置变化短信通知的电话列表 当该手机检测到位置发生变化就会向这个订阅列表里的所有手机发送短信 看到Nokia这个解决方案 男孩们和小雪都应该松一口气 他们各自都可以按照自己正常的生活习惯 只有状态发生变化时候各自才会进行通信

  观察者模式的解决方案

     在上面Nokia的解决方案中就透露出观察者模式的思想 观察者模式定义了对象之间一对多的依赖 当这个对象的状态发生改变的时候 多个对象会接受到通知 有机会做出反馈 在运行的时刻可以动态的添加和删除观察者

  带着这个定义我们来看看尝试实现上面的观察者模式

  首先在观察者模式中我们必须定义一个所有 观察者 都必须实现的接口 这样被观察者向观察者发送消息的时候就可以使用统一的方式 这也符合面相对象原则中的面向接口编程

  //所有观察者都必须实现public interface IBoy //向男孩们显示小雪位置情况 也就是向观察者发送消息 观察者还可以对此做出反馈void Show(string address);using System;//男孩A 一个观察者public class BoyA : IBoypublic void Show(string address)//假设经过处理后为韩文的地址Console WriteLine( A: +address);using System;//男孩B 又一个观察者public class BoyB : IBoypublic void Show(string address) //假设经过处理后为英语的地址Console WriteLine( B: +address);

  下面看看小雪的实现 也就是被观察者 主要看看那个订阅的电话列表和怎样将消息通知给观察者

  using System;using System Collections Generic;public class GPRSMobile//保存一个观察者列表private List<IBoy> boys = null;private string address = ;public GPRSMobile()boys = new List<IBoy>();//添加观察者public void AddBoy(IBoy b)boys Add(b);public void RemoveBoy(IBoy b)boys Remove(b);//通知private void Notify(string address)for (int i = ; i < boys Count; i++)boys[i] Show(address);//位置发生变化public void OnAddressChanaged(string newAddress)//假设这里的地址是中文形式的Notify(newAddress);

     看到上面的代码例子 我们可以给观察者模式的实现总结出这样几条规律 第一 被观察者必须保存著一个观察者列表 第二 所有的观察者必须实现一个统一的接口

  那观察者模式到底有哪些好处呢?在上面的例子中我们可以看到被观察者仅仅依赖于一个实现了观察者接口的列表 我们可以随时的向这个列表添加观察者 而被观察者无须关注观察者是如何实现的 当我们向观察者族中添加一个新的观察者 被观察者无须作任何改变 新的类型只要实现了观察者接口即可

  在上面的描述中我们仿佛看到了面向接口编程无穷的力量 面向接口编程使实现依赖于接口 也就是实现依赖于抽象 这样在被依赖对象发生改变的时候 只要接口没有发生变化时 依赖对象无须作任何变动

     在现实中存在着很多观察者模式的实例 比如在这个全民炒股的时代 每个持有股票的人总是不断的关注著自己所买的股票的走势 有人天天呆在交易大厅里看着屏幕上股票价格的走势 有人在工作时间盯着电脑里股票软件 为此很多公司采取各种各样的政策来制止这种行为 这样不仅影响正常的上班 且股票交易大厅常常人满为患 如果有这样一个服务 只要你订阅一个短信 这个服务就会在你所关注的股票价格发生变动的时候短信通知你 这样你就可以按照正常的顺序来做你的工作

  中的观察者模式

  中 微软给我们带来一个更好的观察者模式的实现 事件-委托

  在Gof的观察者模式中(姑且称之为经典设计模式吧) 观察者必须实现一个统一的接口 里这个接口由委托的签名来保证了里的委托就是一个安全的函数指针(之所以说安全是与以前的C指针相比的 C的函数指针并不包括函数的签名比如参数等东西 所以可以传递一个并不是你期望的函数进去 导致运行时出错 由于这种错误在运行时发生 很难检查出来) Ok 现在以一的委托-事件的例子结束今天的观察者模式吧

     描述 这是一个控制台程序 程序接收一个 到 之间整型的输入 程序接收到输入后开始一个从 到 的循环 当循环到你输入的数字的时候做一些处理 我们将以两种方式来描述这个实例 先用常规的方式 然后采用委托-事件的方式

  public class Programstatic void Main(string[] args)Console WriteLine( Please Input a Number: );int input = Console Read();if (input < || input > )Console WriteLine( Error );for (int i = ; i <= ; i++)if (i == input)//屏幕输出Console WriteLine(i ToString());//弹出提示框MessageBox Show(i ToString());//可能还有其他处理

  看到这个例子有什么感觉?

  循环的代码和处理的代码混在一起 可能还有未知的处理方式添加进来 耦合度非常高 再看的处理方式吧

  namespace Observer//定义一个委托 这里定义了观察者方法的签名 就是一个协议吧public delegate void NumberEventHandler(object sender NumberEventArgs e);//要传递哪些参数到观察者?在这里定义 注意 要继承自EventArgspublic class NumberEventArgs : EventArgspublic NumberEventArgs(int number)_number = number;private int _number;public int Numberget return _number;set _number = value;//观察者模式中的主题public class Subject//定义一个事件 就是委托的实例了public event NumberEventHandler NumberReached;public void DoWithLoop(int number)for (int i = ; i <= ; i++)//触发事件的条件到了if (i == number)NumberEventArgs e = new NumberEventArgs(i);OnNumberReached(e);//注意 这个方法定义为保护的 虚拟的 代表子类还可以进行覆蓋 改变触发事件的行为//甚至可以不触发事件protected virtual void OnNumberReached(NumberEventArgs e)//判断事件是否为null 也就是是否绑定了方法if (NumberReached != null)NumberReached(this e);  public class MainProgrampublic static void Main()Console WriteLine( Please Input a Number: );int input = Console Read();if (input < || input > )Console WriteLine( Error );Subject s = new Subject();//给事件绑定方法 静态的s NumberReached += new NumberEventHandler(msgbox_NumberReached);MainProgram mp = new MainProgram();//给事件绑定方法 实例方法s NumberReached += new NumberEventHandler(nsole_NumberReached);s DoWithLoop(input);Console Read();void console_NumberReached(object sender NumberEventArgs e)Console WriteLine(e Number ToString());static void msgbox_NumberReached(object sender NumberEventArgs e)MessageBox Show(e Number ToString());

  虽然这个例子代码多多了 但是是值得的 事件触发的地方和处理的地方完全分离了 循环的位置不再需要知道有多少个方法正等着处理它

  总结

     经过几篇设计模式文章的介绍 也许有人会觉得设计模式一直在尝试解决几个问题 解藕 封装变化 设计模式一直在为可维护性 可扩展性 灵活性努力着 所以学习设计模式并不是了解设计模式的原型 重要的是了解设计模式的场景和目的 这样你也可以在你自己的工作中总结出自己的设计模式

  有人说中国的数学教育是个错误 学习数学并不是学习那些定理公式 学习那些东西永远是跟在别人的后面 学习数学应该注重数学史的学习 循着数学发展的历史 了解前人是怎样分析问题 解决问题 学习前人的 渔 并不仅仅是为了得到 鱼

    

  本来上面的文章已经写定了 但今天看一MVP的文章又有点新的感触 觉得上面的总结又有点偏颇 学习模式重要的是她的精髓 但是 作为初学者即使知道所有设计原则但是却不知道如何在项目应用 是的 也许学习设计模式也要从 量变 引起 质变 大量的应用 先不管是否是过度设计 到一定的时候也许就会得到思想上的升华

cha138/Article/program/net/201311/11302

相关参考

知识大全 java 设计模式之 观察者模式(Observer)

java设计模式之观察者模式(Observer)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 php设计模式之观察者模式的应用详解

 代码如下:<?php//抽象主题interfaceSubjectpublicfunctionattach($observer);publicfunctiondetach($obser

知识大全 .NET简谈设计模式之(适配器模式)

.NET简谈设计模式之(适配器模式)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  今天我们要学

知识大全 观察者模式 - 设计模式

  观察者模式定义了一个一对多的对象关系一个主体对象对应多个观察者对象当主体对象发生改变时所有它对应的观察者对象都会自动得到通知并更新  本文将给出一个相应的事例具体说明观察者模式是如果工作的这个事例

知识大全 设计模式-快餐简解-观察者模式

  【观察者模式应用场景举例】  比如在玩极品飞车这款游戏每一个车手到达终点的时候都会在其它车手的屏幕上显示某某人以多少时间到达终点的提示其实这就是一个典型的观察者模式的应用观察者模式即是典型的双向一

知识大全 圣斗士星矢的状态模式和观察者模式

  星矢动画片《圣斗士星矢》的男猪脚超级小强怎么打也打不死  雅典娜动画片《圣斗士星矢》的女猪脚自称女神手下有个男人为他卖命  状态模式为了方便的控制状态的变化避免一堆IF/ELSE以及状态规则改变的

知识大全 爪哇语言观察者模式介绍

  简单地说观察者模式定义了一个一对多的依赖关系让一个或多个观察者对象监察一个主题对象这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象使这些观察者对象能够自动更新  观察者模式

知识大全 设计模式与VB .net代码 外观模式,合成模式

设计模式与VB.net代码外观模式,合成模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  外观

知识大全 VB.net 学习设计模式(中介者模式)

VB.net学习设计模式(中介者模式)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!将一些对象的相

知识大全 Java程序性能优化-观察者模式(3)

Java程序性能优化-观察者模式(3)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!