惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
D
Docker
Blog — PlanetScale
Blog — PlanetScale
罗磊的独立博客
美团技术团队
V
V2EX
Last Week in AI
Last Week in AI
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Microsoft Security Blog
Microsoft Security Blog
Microsoft Azure Blog
Microsoft Azure Blog
人人都是产品经理
人人都是产品经理
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
B
Blog RSS Feed
博客园_首页
B
Blog
博客园 - 叶小钗
I
InfoQ
WordPress大学
WordPress大学
L
LangChain Blog
Apple Machine Learning Research
Apple Machine Learning Research
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
About on SuperTechFans
The GitHub Blog
The GitHub Blog
The Register - Security
The Register - Security
MyScale Blog
MyScale Blog
云风的 BLOG
云风的 BLOG
博客园 - 司徒正美
Latest news
Latest news
W
WeLiveSecurity
T
The Exploit Database - CXSecurity.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CERT Recently Published Vulnerability Notes
C
CXSECURITY Database RSS Feed - CXSecurity.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
N
News and Events Feed by Topic
S
Secure Thoughts
The Hacker News
The Hacker News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google DeepMind News
Google DeepMind News

博客园 - YellowWee(端木柒)

Founders at Work: Stories of Startups' Early Days 创业初期的故事 生成自己站点的SiteMap 开通新博客,欢迎大家访问:http://www.yellowwee.com.cn [转载]Fix Your Site With the Right DOCTYPE Java Top Books 自定义DataContext类 [转载]Encrypting Configuration Information in ASP.NET 2.0 Applications 安装 Sql Server Query Visualizer - YellowWee(端木柒) 生活的五项调整 C# 中的扩展方法---Extension methods in C# 《架构师杂志》评述:Scott Guthrie 转自MSDN WPF/Every CTP 发布 使用虚拟机安装vista RTM 配置.net 3.0开发环境 如何在TableAdapter中使用Data Access Application Block的疑问?? 今年的 Jolt 大奖 胡汉三 归来 IssueVision 学习笔记(二)-----为控件添加自定义属性和事件 IssueVision 学习笔记(一)-----使用SoapHeader传递Web Serivices自定义的身份验证数据
IssueVision 学习笔记(三)-----设计模式之OBSERVER(观察者)模式
YellowWee(端木柒) · 2004-06-07 · via 博客园 - YellowWee(端木柒)

   这次我们来看看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中的实现来简单讲述一下.

    在IssueVisionPatterns文件夹下有两个文件ISubject.csIObserver.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.