日期:2014-05-17  浏览次数:20986 次

浅析C#之——Observer, Delegate和event(1)

这些天除了项目之外花时间最多的就是在研究C#里的Delegate和event......
此外,还在写文章的时候无意中研究了一下Observer设计模式...

其实说研究也惭愧,浅尝辄止而已,但还是想把学到的写出来分享一下,第一次写这类文章,面向广大的和我一样的低阶菜鸟级程序猿,还望大师们海涵加指点………………

关键词:
字段:通常指类对象中的成员变量,一般为私有。
属性:C#中较为独特的一种……签名?不知该怎么称呼,就是对字段(私有)添加了get和set方法后,可以像共有变量那样去调用。一般将变量名设置为大写。
方法:通常指类对象中的成员函数。
PS:感觉……所谓的字段、属性、方法等都是在面向对象编程中以对象的视角来看待变量和函数后所产生的称呼;

先来说一下Observer设计模式,其实这个不属于C#独有。它是一个设计模式,其实也是这三者中最重要的一个概念。

引用

观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

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

一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设计方案中最重要的一种。




概念定义啥的网上都能查得到,抽象的概念我就不多说了。接下来想用一组实例来说明这个设计模式。

假设现在有两个对象,分别为消息中心(MessageCenter)和消息库(MessageStore)。现在有一个机制是,消息中心每产生一条新信息,就要在消息库中备份;
先看一个没有运用设计模式的例子:noObserver.cs

using System;

class MessageCenter
{		
	private String messageString; // MessageCenter用来缓存消息的String字段;
	
	// 新建消息;
	public void newMessage(String message)
	{
		Console.WriteLine("New message: " + message + "... [MessageCenter]" );
		this.messageString = message;
	}
	
	// 通知MessageStore有新消息,将其备份入MessageStore;
	public void notice(MessageStore messageStore)
	{
		//messageStore.MessageString = this.messageString;
		//Console.WriteLine("Message: '" + messageString + "' have been stored in MessageStore...");
		messageStore.storeMessage(this.messageString);
	}	
}

class MessageStore
{
	private String messageString;	// MessageStore用户存储消息的String字段;
																// 其实应该是一个String容器用来存储多条消息,不过在此为了简单只放一条消息;

	public String MessageString	
	{
		get{return messageString;}
		set{this.messageString = value;}
	}
	
	public void storeMessage(String message)
  {
    this.messageString = message; 
    Console.WriteLine("Message: '" + this.messageString + "' have been stored in MessageStore..."); 
  }
	
	// 列出MessageStore中已存储的消息;
	public void listMessages()
	{
		Console.WriteLine("Stored message1: '" + this.messageString + "'...[MessageStore]");
	}
}

class Test
{
	public static void Main()
	{
		MessageCenter messageCenter = new MessageCenter();
		MessageStore messageStore = new MessageStore();
		messageCenter.newMessage("Hello world!");	 //新建消息Hello world;
		messageCenter.notice(messageStore);		//通知messageStore有消息需要存储;
		messageStore.listMessages();	//列出messageStore中已经存储的消息;
	}
}
?输出结果:



以上这个例子基本实现了消息中心向消息库存储消息的机制。不过其中有一个很大的问题是:
存储消息的方法被直接写在了MessageCenter的notice()方法体中,这使得消息库无法自己决定存储的方式;
我们可以做一些改进,就是将存储消息的方式写成一个属于MessageStore的方法,随后在MessageCenter的notice()方法中直接调用messageStore.storeMessage()方法:

class MessageCenter
{
  ...
  // 通知MessageStore有新消息,将其备份入MessageStore;
  public void notice(MessageStore messageStore)
  {
	//messageStore.MessageString = this.messageString;
	//Console.WriteLine("Message: '" + messageString + "' have been stored in MessageStore...");
	messageStore.storeMessage(this.messageString);
  }
  ...
}
class MessageStore
{
  ...
  public void storeMessage(String message)
  {
    this.messageString = message; 
    Console.WriteLine("Message: '" + this.messageString + "' have been stored in MessageStore..."); 
  }
  ...
}


但这样也有一个问题,就是MessageCenter在写notice方法的时候必须事先知道MessageStore中的存储消息的方法名,否则便无法调用,但倘若写MessageCenter和写MessageStore的程序猿不是同一个人,就需要很麻烦的事先确定好方法的命名。那如何避免这个麻烦的问题呢?
一个解决问题的方法是,让MessageCenter作者提供一个供MessageStore对象继承的抽象类或接口,并在其中定义一个名为storeMessage的虚方法,这样的话,MessageStore就只需要继承这个抽象类或接口并重写storeMessage()方法以实现自己想要的存储方法,而MessageCenter也可以在不知道存储方法的情况下在notice()方法中调用MessageStore的storeMessage()方法,从而实现解耦;
代码如下(其实只要修改很少的部分):tryObserver.cs