分享
 
 
 

[原创]IssueVision 学习笔记(三)-----设计模式之OBSERVER(观察者)模式

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

这次我们来看看IssueVision中的对设计模式的应用,IssueVision主要使用了OBSERVER(观察者)模式和COMMAND(命令)模式.今天就来看看OBSERVER(观察者)模式在IssueVision中的应用,它在IssueVision中扮演着重要角色.

"四人帮"GoF是这样定义OBSERVER(观察者)模式的------定义对象间的一种一对多的关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知,并被自动更新.

从定义可以看出,OBSERVER(观察者)模式逻辑上需要两组对象来实现.首先它必需要有发布者(Publish),也可称为被观察的目标(Subject)(习惯上都称它为目标Subject,后面我们都称它作目标Subject),另外就是订阅者(Subscribe),习惯上称为观察者(Observer).一个目标对象对应多个观察者对象,目标对象发生变化时,所有在目标对象中注册的观察者对象会得到通知,自动更新自己.

在应用程序开发过程中,往往都要求用户界面和业务逻辑分离,划定清晰的界限.因为应用程序要求能快速的更改用户界面并且不能对应用程序其他部分产生连带影响,而且业务逻辑也会发生变化并要求这一切变化与用户界面无关.观察者(Observer)就是解决此问题最常用的设计模式,它非常有助于在系统中各个对象之间划分清晰的界限.

下图最好的展示了这种形式,观者者(observer)们(表格对象,柱状图对象和饼状图对象)都依赖数据对象Subject,所以数据对象Subject的所有改变都会通知它们.但它们互相之间并不知道对方的存在,表格对象不知道其他表格对象或者其他柱状图对象的存在.对于数据对象Subject可以有任何多的观察者,这些观察者都能在Subject对象发生改变时得到通知,使自己的状态与Subject同步:

好吧,概念就说这么多吧,我们来看一下OBSERVER(观察者)模式的实现.通用的OBSERVER(观察者)模式的实现我在这就不说了,可以参考GoF的设计模式和Java与模式等书.我们就来专注于.NET框架中OBSERVER(观察者)模式的实现.

.NET框架引入了委托和事件,它们提供了更新,功能更强大的方法来实现OBSERVER(观察者)模式.(关于委托和事件的更多内容请参考相关文档).如果你不熟悉委托和事件,实现OBSERVER(观察者)模式则需要作很多工作(像在Java中实现那样).下面我就以IssueVision中的实现来简单讲述一下.

在IssueVision中Patterns文件夹下有两个文件ISubject.cs和IObserver.cs.它们分别定义了目标(Subject)对象和观者者(Observer)对象的接口,代码如下:

ISubject.cs

namespace IssueVision

{

// ISubject is a simple marker interface that supports the implementation

// of the Observer pattern in IssueVision.

public interface ISubject

{

}

}

IObserver.cs

namespace IssueVision

{

// IObserver is a simple interface that supports the implementation of the

// Observer pattern in IssueVision.

public interface IObserver

{

ISubject Subject

{

set;

}

}

}

大家可能发现,这两个接口几乎为空,什么都没有定义,那这两个接口的作用是什么呢?其实定义这两个接口的作用主要为编码的"规范化",只要类实现了这两个接口任何一个,那么就代表此类就实现了OBSERVER(观察者)模式,并且很明显的知道谁是Subject,谁是Observer.

IssueVision中的IssueSubject组件就实现ISubject接口,它是IssueVision中实现OBSERVER(观察者)模式最主要的部分,也是IssueVision中最最复杂的一个类.我们慢慢一点一点来分析它(当然之分析OBSERVER(观察者)模式相关部分):

IssueSubject.cs

public class IssueSubject : Component, ISubject

首先定义类IssueSubject继承自Component和ISubject,从这里和类名可以看出,此类是作为OBSERVER(观察者)模式中的目标(Subject)实现的.目标(Subject)对象要求实现对观察者(Observer)的注册(Register)和通知,Component类就是用来实现注册(Register)的.大多数目标(Subject)对象的实现并不是并非将观察者(Observer)的引用直接存储在自己的实例变量中,而是将此人物委托给一个单独的对象(通常为一个容器)Component类就是这样一个容器,下面代码显示了如何用Component类容器来存储对观察者(Observer)对象的引用注册(Register)

public IssueSubject(IContainer Container) : this()

{

Container.Add(this);

}

我们来看一下它是如何完成注册(Register)的,首先我们找到一个观察者(Observer)对象的实现,Controls/IssueTreeView 用户控件就是一个观察者(Observer)对象.它实现了IObserver接口.

Controls/IssueTreeView.cs

namespace IssueVision

{

// The IssueTreeView user control implements the view selection ui for IssueVision

public class IssueTreeView : UserControl, IObserver

{

.....

private TreeView trvViews;

private ImageList images;

private IssueSubject m_subject = null;

private const string m_fontname = "Tahoma";

private IContainer components;

public virtual ISubject Subject //ISubject接口的方法

{

set

{

m_subject = (IssueSubject)value;

.....

}

}

Pane/StaffPane用户控件引用了此IssueTreeView,它同样也是观察者(Observer)对象.

Pane/StaffPane.cs

namespace IssueVision

{

public class StaffPane : UserControl, IObserver

{

....

private IssueTreeView itvViews;

private IContainer components = null;

// IObserver.Subject

public ISubject Subject

{

set

{

itvViews.Subject = (IssueSubject)value;

}

}

在MainForm.cs中调用此用户控件代码如下:

private IssueSubject m_issueSubject = null;

.....

m_issueSubject = new IssueSubject(this.components); //调用IssueSubject的构造函数

paneStaff.Subject = m_issueSubject;

通过调用IssueSubject的构造函数,是此观察者(Observer)对象注册到了目标(Subject)对象中.(通过容器的Container.Add())

这样就完成了OBSERVER(观察者)模式的第一步,观察者(Observer)对象的注册.下面我们来看第二步,目标(Subject)对象如何通知观察者(Observer)对象

这就需要使用到委托和事件了.在回来看IssueSubject

IssueSubject.cs

public class IssueSubject : Component, ISubject

{

#region Delagate and Event Declarations

.......

public delegate void ConflictDataChangedEventHandler(object sender, EventArgs e);

public delegate void LookupDataChangedEventHandler(object sender, EventArgs e);

// ConflictDataChanged changes when a conflict is resolved, or new conflicts are

// detected.

public virtual event ConflictDataChangedEventHandler ConflictDataChanged;

// LookupDataChanged is raised when lookup data is downloaded from the server

public virtual event LookupDataChangedEventHandler LookupDataChanged;

......

在IssueSubject中申明委托和事件,观察者(Observer)对象登记这些事件,那么当IssueSubject改变后,激活一个事件,那么所有的观察者(Observer)对象都能得到这个改变的通知,从而激活相应的处理.

再看Controls/IssueTreeView.cs

namespace IssueVision

{

// The IssueTreeView user control implements the view selection ui for IssueVision

public class IssueTreeView : UserControl, IObserver

{

.....

private TreeView trvViews;

private IssueSubject m_subject = null;

private IContainer components;

public virtual ISubject Subject //ISubject接口的方法

{

set

{

m_subject = (IssueSubject)value;

//登记IssueSubject的事件,并交给相关方法处理事件

m_subject.LookupDataChanged += new IssueSubject.LookupDataChangedEventHandler(this.Subject_LookupDataChanged);

m_subject.ConflictDataChanged += new IssueSubject.ConflictDataChangedEventHandler(this.Subject_ConflictDataChanged);

}

}

最后,在IssueSubject中激活这些事件.

IssueSubject.cs

private void LoadIssueData()

{

.......

m_dataSet.DataSetName = "IssueSubject";

if (LookupDataChanged != null)

{

LookupDataChanged(this, EventArgs.Empty);

}

}

通过这么简单的几个步骤,就实现了OBSERVER(观察者)模式,.NET框架提供的委托和事件机制很大的简化了模式的实现.

CopyRight © YellowWee 2004. All Right Reserved.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有