一口一个设计模式--观察者模式中。我们已经知道怎样应用观察者模式,但通过近期的深入学习,发现观察者模式存在下面缺陷:

1.抽象通知者依赖于抽象观察者;

2.每一个详细观察者被调用的方法必须一致。

比方在机房收费系统中关于观察者模式的应用例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXV3ZW56aGU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

这个设计存在下面问题:

1.抽象通知者须要把抽象观察者中的全部详细对象加入到集合中,以备向每一个详细观察者发送通知消息。

2.在发送通知消息时。详细观察者中被通知的方法必须一致,否则详细通知者无法完毕遍历;

3.更新卡内剩余金额、更新学生上机状态和保存学生上机记录这三个类没什么同样的地方。抽象出来的抽象观察者有点牵强。

经过苦苦的思索,我发现用C#中的托付和事件机制解决上述问题。代码结构例如以下:

抽象通知者:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 观察者模式_托付
{
public interface Informer
{
void Notify();
string Action { get; set; }
}
}

详细通知者--正常下机:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 观察者模式_托付
{
public class Down : Informer
{
//声明一个托付
public delegate void EventHandler();
//为托付EventHandler加入事件Update
public event EventHandler Update; public void Notify()
{
this.Update();
} private string action; public string Action
{
get { return action; }
set { action = value; }
}
}
}

详细通知者--强制下机:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 观察者模式_托付
{
public class ForceDown : Informer
{
//声明一个托付
public delegate void EventHandler();
//为托付EventHandler加入事件Update
public event EventHandler Update; public void Notify()
{
this.Update();
} private string action;
public string Action
{
get { return action; }
set { action = value; }
}
}
}

这个我们不须要抽象观察者,直接详细观察者--更新卡内剩余金额:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 观察者模式_托付
{
public class UpdateBalance
{
protected Informer dn;
public UpdateBalance(Informer dn)
{
this.dn = dn;
}
public void ModifyBalance()
{
Console.WriteLine("{0}。该卡要下机,更新剩余金额! ", dn.Action);
}
}
}

详细观察者--更新学生上机状态:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 观察者模式_托付
{
public class OffLine
{
protected Informer dn;
public OffLine(Informer dn)
{
this.dn = dn;
}
public void DelOnlineInfo()
{
Console.WriteLine("{0}!该卡要下机,删除正在上机表中的该卡信息!", dn.Action);
}
}
}

详细观察者--保存学生上机记录:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 观察者模式_托付
{
public class SaveRec
{
protected Informer dn;
public SaveRec(Informer dn)
{
this.dn = dn;
}
public void SaveLineRec()
{
Console.WriteLine("{0}!该卡要下机,保存上机记录信息!", dn.Action);
}
}
}

main方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 观察者模式_托付
{
class Program
{
static void Main(string[] args)
{
Down dn = new Down(); OffLine ol = new OffLine(dn);
UpdateBalance up = new UpdateBalance(dn);
SaveRec sr = new SaveRec(dn); dn.Update+=new Down.EventHandler(ol.DelOnlineInfo);
dn.Update += new Down.EventHandler(up.ModifyBalance);
dn.Update += new Down.EventHandler(sr.SaveLineRec); dn.Action = "刷卡下机";
dn.Notify();
}
}
}

程序运行结果例如以下所看到的:

通过运行结果,我们能够发现,在main方法中的正常下机事件dn.Update发生后,通过托付Down.EventHandler绑定到dn.Update事件上的三个方法ol.DelOnlineInfo、up.ModifyBalance、sr.SavelineRec都会被运行,达到观察者模式的效果。

如今我们能够发现:抽象通知者不再依赖于抽象观察者,由于抽象通知者通过托付通知详细观察者;详细观察者中被调用的方法也不是必需一致。由于仅仅需把想要运行的方法绑定到事件上即可。详细通知者也不必存在共性,不必牵强的对这三个类进行抽象。托付+事件完美解决上述问题。

再看C#中的托付和事件的更多相关文章

  1. Android菜鸟的成长笔记(17)—— 再看Android中的Unbounded Service

    原文:Android菜鸟的成长笔记(17)-- 再看Android中的Unbounded Service 前面已经写过关于startService(Unbounded Service)的一篇文章:&l ...

  2. 再看 Java 中的单例

    此前面试遇到了单例问题,本以为已经背的滚瓜烂熟,没想到被问单例如何避免被反射和序列化破坏,虽然后来还是等到了通知,但还是复习一下单例的实现方式,并学习防止反射和序列化破坏的手段. 基本实现方式 其他相 ...

  3. 再看Ajax

    再回顾Ajax相关的内容,再次梳理学习还是很有必要的,尤其是实际的开发中,ajax更是必不可少,仔细学习以便避免不必要的错误. 文章导读: --1.使用XMLHttpRequest---------- ...

  4. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  5. 探究JavaScript中的五种事件处理程序

    探究JavaScript中的五种事件处理程序 我们知道JavaScript与HTML之间的交互是通过事件实现的.事件最早是在IE3和Netscape Navigator 2中出现的,当时是作为分担服务 ...

  6. C#中的委托(Delegate)和事件(Event)

    原文地址:C#中的委托(Delegate)和事件(Event) 作者:jiyuan51 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式--观察者(Obs ...

  7. C#托付和事件

    C#托付.我看了非常长时间的资料和帖子, 曾经对托付的理解就是托付事实上就是将一个方法作为參数传递给第一个方法. 如今对托付的认识则变了一些的,托付能够实现: 1.在两个不能直接调用的方法之间做为桥梁 ...

  8. SQL Server 扩展事件(Extented Events)从入门到进阶(2)——在GUI中创建基础扩展事件

    本文属于 SQL Server 扩展事件(Extented Events)从入门到进阶 系列 第一篇文章中提到了如何在Profiler中创建跟踪(trace),并以服务器端(server-side)跟 ...

  9. JQuery中的对象和事件

    一:JQuery 对象和 Dom 对象 在使用 JQuery 过程中,我们一般(也是绝大多数情况下,除非我们使用了第二个框架)只有两类对象,即:JQuery 对象和 Dom 对象.Dom 对象指的是普 ...

随机推荐

  1. Java主流Web Service框架介绍:CXF和Axis2

    CXF和Axis2是目前java平台上最主流的两个框架,虽然两个项目都隶属ASF,但却是基于不同思想和风格实现的,因此也各有所长.   CXF:http://cxf.apache.org/ 是由过去的 ...

  2. vue-cli项目优化,缩短首屏加载时间

    1.大文件定位 我们可以使用webpack可视化插件Webpack Bundle Analyzer 查看工程js文件大小,然后有目的的解决过大的js文件. 安装:npm install --save- ...

  3. SecureRandom-随机数的生成

    随机数:算法+种子 随机数据不随机 学习了:https://www.cnblogs.com/deng-cc/p/8064481.html StringBuffer buffer = new Strin ...

  4. Cognos Report Studio 链接查询需要注意的地方2

    在Report Studio里面用SQL设计报表,查询2,查询3 要链接一般按条件  a1=b1 在选择链接方式需要注意的地方: 默认链接 外部链接 需要设置打开FM,打开报表设计引用的数据包(FM- ...

  5. STM8S AD转换

    //不说那么多了,直接上程序 void ADC1_DeInit(void) { ADC1->CSR = ADC1_CSR_RESET_VALUE; ADC1->CR1 = ADC1_CR1 ...

  6. Fusioncharts的导出图片訪问官网问题

    Fusioncharts3.5使用自带的导出功能,须要訪问官网 问题描写叙述:使用fusioncharts自带的exportchart方法来导出图片的时候.要訪问export.api3.fusionc ...

  7. 【CSWS2014 Main Conference】Some Posters

    随机选了几张POSTER,之前没做过POSTER的同学可以看一下文字.图片.布局以及每个版块的小标题,以后如果需要做poster就容易多了. 据说这种Poster一张需要60RMB左右. 其中第5幅是 ...

  8. Android 之 AndroidManifest.xml 详解(一)

    当Android启动一个应用程序组件之前,它必须知道哪些个组件是存在的,所以开发人员在开发过程中,必须将应用程序中出现的组件一一在AndroidManifest.xml文件中" 声明 &qu ...

  9. 上传的文件放在SVN服务器的哪个目录下

    SVN服务器版本库有两种格式,一种为FSFS,一种为BDB 把文件上传到SVN版本库后,上传的文件不再以文件原来的格式存储,而是被svn以它自定义的格式压缩成版本库数据,存放在版本库中. 如果是FSF ...

  10. Java从零开始学一(环境配置)

      一.JDK的下载和安装 1.下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151. ...