`
warlock333
  • 浏览: 5099 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

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

    博客分类:
  • C#
阅读更多

这些天除了项目之外花时间最多的就是在研究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

using System;

interface ReceiveMessage
{
	void storeMessage(String message);
}

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)
	public void notice(ReceiveMessage messageStore) //将对象参数类型换成接口类型;
	{
		//messageStore.MessageString = this.messageString;
		//Console.WriteLine("Message: '" + messageString + "' have been stored in MessageStore...");
		messageStore.storeMessage(this.messageString);
	}	
}

class MessageStore : ReceiveMessage
{
	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..."); 
  }
  */
  
  public void storeMessage(String message) //实现接口方法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与MessageStore之间的一对一关联,耦合度也较松。
但这样还是不够灵活,如果想与MessageCenter关联的对象不只MessageStore一个,且希望能实现动态关联,即想关联的时候关联,不想关联的时候就可以断开,那就需要对代码做进一步修改。在此,我们可以再添加一个将与MessageCenter关联的MessageChecker对象,并在MessageCenter中设置一个ArrayList用来存储所有继承了ReceiveMessage接口的消息接收者(观察者Observer),并构造两个对其进行操作的addReceiver()方法和removeReceiver()方法,用来添加和移除receiver(观察者Observer);随后,修改notice方法,使其遍历ArrayList并调用每个receiver的storeMessage()方法。
代码如下:Observer.cs

using System;
using System.Collections;

interface ReceiveMessage
{
	void storeMessage(String message);
}

class MessageCenter
{		
	private String messageString; // MessageCenter用来缓存消息的String字段;
	private ArrayList receiverList = new ArrayList();
	
	//添加消息接受者;
	public void addReceiver(ReceiveMessage receiver)
	{
		receiverList.Add(receiver);
	}
	
	//移除消息接受者;
	public void removeReceiver(ReceiveMessage receiver)
	{
		receiverList.Remove(receiver);
	}
	
	// 新建消息;
	public void newMessage(String message)
	{
		Console.WriteLine("New message: " + message + "... [MessageCenter]" );
		this.messageString = message;
	}
	
	// 通知MessageStore有新消息,将其备份入MessageStore;
	//public void notice(MessageStore messageStore)
	/*
	public void notice(ReceiveMessage messageStore) //将对象参数类型换成接口类型;	
	{
		//messageStore.MessageString = this.messageString;
		//Console.WriteLine("Message: '" + messageString + "' have been stored in MessageStore...");
		messageStore.storeMessage(this.messageString);
	}
	*/
	public void notice()	//// 通知所有已注册的receiver有新消息,并调用其storeMessage方法;
	{
		foreach(Object receiver in receiverList)
		{
			(receiver as ReceiveMessage).storeMessage(this.messageString);
		}
	}	
}

class MessageStore : ReceiveMessage
{
	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..."); 
  }
  */
  
  public void storeMessage(String message)  //实现接口方法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 MessageChecker : ReceiveMessage
{
	private String checkResult;
	
	public void storeMessage(String message)  //实现接口方法storeMessage(String message);
	{
		this.checkResult = "OK!";
		Console.WriteLine("The message: '" + message + "' has been checked...");
	}
	
	public void showCheckResult()
	{
		Console.WriteLine("The checkResule is: " + this.checkResult + " [MEssageChecker]");
	}
}

class Test
{
	public static void Main()
	{
		MessageCenter messageCenter = new MessageCenter();
		MessageStore messageStore = new MessageStore();
		MessageChecker messageChecker = new MessageChecker();
		
		messageCenter.addReceiver(messageStore);
		messageCenter.addReceiver(messageChecker);
		
		messageCenter.newMessage("Hello world!");	 //新建消息Hello world;
		//messageCenter.notice(messageStore);		//通知messageStore有消息需要存储;
		messageCenter.notice();
		messageStore.listMessages();	//列出messageStore中已经存储的消息;
		messageChecker.showCheckResult(); //显示messageChecker的checkResule;
	}
}


输出结果:


以上,就是著名的Observer设计模式的基本实现。

其中的各个继承了ReceiveMessage的对象receiver就对应了设计模式中的Observer观察者,而MessageCenter就是被观察者。被观察中中有一个用来记录观察者信息的表ArrayList receiverList,并在发生相应动作的时候调用notice方法通知所有已注册过的观察者,从而实现一对多的发布-订阅机制。

==================================================================================

 

  • 大小: 1.8 KB
  • 大小: 2.9 KB
  • 大小: 2.9 KB
  • 大小: 2.4 KB
  • 大小: 7.1 KB
分享到:
评论

相关推荐

    Observer模式

    Observer模式,也被称为“发布-订阅”模式,是软件设计模式中的行为模式之一。它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。Observer模式是实现...

    C#范例——研究生信息系统,提供详细的代码,控件,适合C#初学者借鉴!

    【C#范例——研究生信息系统】是一个专门为C#初学者设计的学习资源,旨在帮助他们理解和掌握C#编程语言在实际项目中的应用。这个系统可能是针对研究生教育管理的一个完整解决方案,涵盖了学生信息管理、课程管理、...

    深入浅出设计模式(中文版电子版)

    5.7.3C#实例——猫和老鼠 238 5.7.4C#实例——股票变化 241 5.7.5Java实例——监控系统 245 5.7.6优势和缺陷 248 5.7.7应用情景 248 5.8StatePattern(状态模式) 248 5.8.1定义 248 5.8.2现实例子——心情...

    C#中的委托、事件和Observer设计模式使用方法示例

    在C#编程语言中,委托、事件和Observer设计模式是构建高效、可扩展的应用程序的重要概念。这篇文档将深入探讨这些主题,以帮助你更好地理解它们的用途和实现方式。 首先,我们来看委托(Delegate)。委托在C#中相当...

    iOS基础——通知代理之NSNotificationCenter、Delegate

    在iOS开发中,通知代理是实现对象间通信的重要机制,主要分为两个方面:NSNotificationCenter和Delegate。这两种方式都允许一个对象监听并响应其他对象的事件,但它们各自有其特性和适用场景。 首先,我们来详细...

    详解C#委托,事件,Observer设计模式

    在C#中,事件和委托是实现Observer模式的有效工具。 通过事件,发布者可以在特定条件下触发通知,而订阅者则可以通过添加事件处理程序来响应这些通知。这种方式不仅降低了对象之间的耦合度,还提高了系统的灵活性和...

    C# 委托和事件在.NET Framework详解

    在C#中,委托可以用于实现Observer设计模式,从而使得代码更加灵活和可扩展。 委托和事件是C#中的重要概念,广泛应用于各个领域。通过了解委托和事件的概念、应用场景和设计模式,可以提高开发效率和代码质量。

    C#中的委托delegate用法的示例详解

    【C#中的委托delegate用法的示例详解】 在C#编程语言中,委托是类型安全的函数指针,允许我们将方法作为参数传递给其他方法,或者存储在类的字段中,以便稍后调用。这种特性使得委托成为C#中实现事件处理和回调机制...

    C#设计模式(17)——观察者模式(Observer Pattern).pdf

    从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户。从中,我们就可以得出观察者模式的定义。  观察者模式定义了一种一对多的依赖关系,让多个观察者对象...

    c# 中的委托 详细讲解了如何使用c#中的委托机制

    下面我们将深入讲解委托的定义、使用委托的原因、事件的由来、委托和事件对 Observer 设计模式的意义、.Net Framework 中的委托和事件。 委托的定义 委托是一个类型,可以将方法作为参数传递给它,然后在后续使用时...

    设计模式代码——c#

    C#设计模式(23种设计模式) 1. 单件模式(Singleton Pattern) 2. 抽象工厂(Abstract Factory) 3. 建造者模式(Builder) 4. 工厂方法模式(Factory Method) 5. 原型模式(Prototype) 结构型: 6. 适配器...

    Observer-based H∞ Event-triggered Control for Piecewise Affine Systems

    线性矩阵不等式(LMI)是数学中处理线性矩阵之间关系的一种方法,因其在处理约束条件和优化问题时具有方便易用的特点,常被用于控制系统的稳定性分析和控制器设计。 蒋永豪与吴炜的这篇论文中,结合了观测器理论、...

    Observer设计模式实例

    1. **松耦合**:Subject和Observer之间是弱耦合的,Subject的改变不会直接影响到Observer,反之亦然。 2. **可扩展性**:添加新的Observer或修改现有Observer的行为都非常灵活,不会影响到其他部分。 3. **响应性**...

    委托实现C#观察者模式简单例子

    Observer observer1 = new ConcreteObserver(); subject.Attach(observer1); subject.ChangeState(); // 触发状态改变,从而调用所有观察者的Update方法 } ``` 通过这个简单的例子,我们展示了如何使用C#的...

    C#面向对象设计模式纵横谈(19):(行为型模式) Observer 观察者模式 (Level 300)

    在C#中实现观察者模式,通常涉及两个关键角色:主题(Subject)和观察者(Observer)。主题是被观察的对象,它维护了一个观察者列表,并提供方法供观察者注册和注销;观察者则表示对主题状态变化感兴趣的实体,它们...

    重温Observer模式--热水器·改

    在这个“重温Observer模式--热水器·改”的讨论中,作者将再次阐述如何不依赖C#的委托和事件来实现Observer模式,而是采用GOF(GoF,Gang of Four)的经典方式。 在Observer模式中,有两个核心角色:Subject(主题...

    委托、事件与Observer设计模式

    委托、事件和Observer设计模式是面向对象编程中的关键概念,特别是在C#中有着广泛的应用。本文将深入探讨这三个概念,并通过实例帮助初学者理解和掌握它们。 首先,让我们从委托(Delegate)开始。委托在C#中可以被...

    《设计模式--基于C#的工程化实现及扩展》.(王翔)_《0528》.rar

    行为型模式则关注对象之间的交互和职责分配,如策略模式(Strategy)、观察者模式(Observer)和责任链模式(Chain of Responsibility)等,它们有助于提高代码的灵活性和可扩展性。 在C#中,设计模式的实现往往...

Global site tag (gtag.js) - Google Analytics