`
wyf
  • 浏览: 433431 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

C# 观察者模式(Event)实现

阅读更多
一、   观察者模式

目的
概述
原理

二、   C#中的观察者模式

概述
模型与观察者基类
优点

三、   事例

题目:猫大叫,两只老鼠开始逃跑,主人醒来,宝宝也醒来了并且哭了起来

解决方案:
1.    建立模型(目标基类)
2.    建立观察者基类(单行为,多行为)
3.    建立具体目标
4.    建立具体观察者
5.    运行测试

 

一、      观察者模式

目的

我们都知道解决一个问题有N种解决方式,但在面向对象的设计中如何能做到“高内聚,低耦合”,设计可重用的对象才是我们追求的。在设计过程中,我们经常会接触到一种情况:一个对象的行为引发其它多个对象相应的行为。这时我们便可以通过观察者模式的设计思想来设计对象模型。

概述

观察者模式(Observer Pattern)是设计模式中行为模式的一种,它解决了上述具有一对多依赖关系的对象的重用问题。此模式的参与者分为两大类,一类是被观察的目标,另一类是观察该目标的观察者们。正因为该模式是基于“一对多”的关系,所以该模式一般是应用于由一个目标对象和N个观察者对象组成(当然也可以扩展为有多个目标对象,但我们现在只讨论前者)的场合。当目标对象的状态发生改变或做出某种行为时,正在观察该目标对象的观察者们将自动地、连锁地作出相应的响应行为。

原理

我们可以把观察目标理解为主动方、发布方、主体等;把观察者理解为被动方、订阅方、观察器等。目标是整个行为链的源头,其它观察者都依赖于它的变化而作出响应。为了实现低耦合,我们不能使用“直接调用”的方式而需要利用“订阅(清单)-通知”的机制去完成设计。通俗地说就是观察者向目标“订阅”它的改变,而目标发生改变后就“通知”所有已经“订阅”了它的改变的观察者,从而执行“订阅”的内容。这种机制的好处在于降低耦合度,分工明确,目标只负责在自身状态发生改变或做出某种行为时向自身的订阅清单发出“通知”,而不是直接调用观察者的行为(方法);观察者只负责向目标“订阅”它的变化,以及定义自身在收到目标“通知”后所需要做出的具体行为(也就是订阅的内容)。就像我们向出版社订阅报刊一样,出版社有新一期报刊发行时并不是直接跟每位订阅者联系,而是“通知”订阅者名单按顺序给每位订阅者发送所订报刊。

 

二、      C#中的观察者模式

概述

每种编程架构及程序语言,对观察者模式都有不通的具体实现。在.NET框架中,C#语言使用委托以及事件,可以很好的实现观察者模式。委托相当于“订阅清单”的角色,当目标中关联了该委托的事件被触发时,则委托将自动按序执行观察者注册于委托中的方法。

模型与观察者基类

我们把观察者模式的参与者都描述为派生自模型及观察者二个抽象基类的类。模型规划了事件,而观察者则规划了订阅及行为。

模型需要做的只是声明委托以及声明委托类型的事件。当然,还可以附加上封装了触发委托事件的方法。所有派生自模型的类都是具体目标,它们所要做的只是在适当的场合触发事件。(即发出“通知”)。

在观察者基类中,我们通过构造器将抽象的响应方法注册(订阅)于委托事件中。所有派生自观察者基类的类都是具体观察者。因为订阅行为已经在抽象基类完成,具体观察者需要做的只是通过覆盖观察者基类的方法去定义具体需要响应的行为,和通过构造器把需要观察的具体目标传递给基类构造器。

优点

通过对模型与观察者基类的分析可知,委托与事件的机制几乎消除了这两个模块之间的耦合,灵活性提高了很多。如果需要增加观察者,则只需要覆盖基类抽象方法及把观察目标传递给基类。

 

三、      事例

题目:猫大叫,两只老鼠开始逃跑,主人醒来,宝宝也醒来了并且哭了起来.

解决方案:

1.   建立模型(目标基类)

 

using System;

 

namespace DelegateEvent

{

    /**//// <summary>

    ///     在Observer Pattern(观察者模式)中,此类作为所有Subject(目标)的抽象基类

    /// 所有要充当Subject的类(在此事例中为"猫")都继承于此类.

    ///     我们说此类作为模型,用于规划目标(即发布方)所产生的事件,及提供触发

    /// 事件的方法.

    ///     此抽象类无抽象方法,主要是为了不能实例化该类对象,确保模式完整性.

    ///     具体实施:

    ///     1.声明委托

    ///     2.声明委托类型事件

    ///     3.提供触发事件的方法

    /// </summary>

    public abstract class ModelBase

    {

        public ModelBase()

        {

        }

        /**//// <summary>

        /// 声明一个委托,用于代理一系列"无返回"及"不带参"的自定义方法

        /// </summary>

        public delegate void SubEventHandler(); 

        /**//// <summary>

        /// 声明一个绑定于上行所定义的委托的事件

        /// </summary>

        public event SubEventHandler SubEvent;

 

        /**//// <summary>

        /// 封装了触发事件的方法

        /// 主要为了规范化及安全性,除观察者基类外,其派生类不直接触发委托事件

        /// </summary>

        protected void Notify()

        {

            //提高执行效率及安全性

            if(this.SubEvent!=null)

                this.SubEvent();

                

        }

    }

}


 

 

2.   建立观察者基类(单行为,多行为)

//--------------------单行为---------------------


 

using System;

 

namespace DelegateEvent

{

    /**//// <summary>

    ///     在Observer Pattern(观察者模式)中,此类作为所有Observer(观察者)的抽象基类

    /// 所有要充当观察者的类(在此事例中为"老鼠"和"人")都继承于此类.

    ///     我们说此类作为观察者基类,用于规划所有观察者(即订阅方)订阅行为.

    ///     在此事例中,规划了针对目标基类(ModelBase)中声明的"无参无返回"委托的一个

    /// 方法(Response),并于构造该观察者时将其注册于具体目标(参数传递)的委托事件中.

    ///     具体实施过程:

    ///     1.指定观察者所观察的对象(即发布方).(通过构造器传递)

    ///     2.规划观察者自身需要作出响应方法列表

    ///     3.注册需要委托执行的方法.(通过构造器实现)

    /// </summary>

    public abstract class Observer

    {

        /**//// <summary>

        /// 构造时通过传入模型对象,把观察者与模型关联,并完成订阅.

        /// 在此确定需要观察的模型对象.

        /// </summary>

        /// <param name="childModel">需要观察的对象</param>

        public Observer(ModelBase childModel)

        {

            //订阅

            //把观察者行为(这里是Response)注册于委托事件

            childModel.SubEvent+=new ModelBase.SubEventHandler(Response);

        }

 

        /**//// <summary>

        /// 规划了观察者的一种行为(方法),所有派生于该观察者基类的具体观察者都

        /// 通过覆盖该方法来实现作出响应的行为.

        /// </summary>

        public abstract void Response();

    }

}


 

 

//-------------------多行为-------------------

 

 

 

using System;

 namespace DelegateEvent

{

    /**//// <summary>

    /// 定义了另一个观察者基类.该观察者类型拥有两个响应行为.

    /// 并在构造时将响应行为注册于委托事件.

    /// (具体描述请参照另一观察者基类Observer)

    /// </summary>

    public abstract class Observer2

    {

        /**//// <summary>

        /// 构造时通过传入模型对象,把观察者与模型关联,并完成订阅.

        /// 在此确定需要观察的模型对象.

        /// </summary>

        /// <param name="childModel">需要观察的对象</param>

        public Observer2(ModelBase childModel)

        {

            //订阅

            //把观察者行为(这里是Response和Response2)注册于委托事件

            childModel.SubEvent+=new ModelBase.SubEventHandler(Response);

            childModel.SubEvent+=new ModelBase.SubEventHandler(Response2);

            

        }

        /**//// <summary>

        /// 规划了观察者的二种行为(方法),所有派生于该观察者基类的具体观察者都

        /// 通过覆盖该方法来实现作出响应的行为.

        /// </summary>

        public abstract void Response();

        public abstract void Response2();

    }

}
 


3.   建立具体目标

 

 

 

using System;

 namespace DelegateEvent

{

    /**//// <summary>

    ///     此类为观察者模式中的具体目标(即具体发布方),其继承于模型.

    /// 其中包含(调用)了在模型中被封装好的触发委托事件的方法.

    /// </summary>

    public class Cat:ModelBase

    {

        public Cat()

        {

        }

        /**//// <summary>

        /// 定义了猫的一种行为----大叫

        /// </summary>

        public void Cry()

        {

            System.Console.WriteLine("Cat Cry..");

            //调用了触发委托事件的方法.

            //通知委托开始执行观察者已订阅的方法.

            this.Notify();  

         }

    }

}

 

 

4.   建立具体观察者

//--------------具体观察者(老鼠)-------------


 

using System;

 namespace DelegateEvent

{

    /**//// <summary>

    ///     此类为观察者模式中的具体观察者(即具体发布方),其继承于观察者基类.

    /// 其中覆盖了观察者基类规划好的方法,实现了响应的具体行为.

    /// </summary>

    public class Mouse:Observer

    {

        /**//// <summary>

        /// 观察者可以拥有自己的成员(字段或者方法).

        /// 在此事例中增加了"老鼠的名字"

        /// </summary>

        private string name;

        /**//// <summary>

        ///     构造时确定观察者所需要观察的对象(具体目标),并传递给观察者基类构造器,

        /// 实现响应行为(方法)的订阅.另外,为观察者实例初始化成员.

        /// </summary>

        /// <param name="name">老鼠的名字</param>

        /// <param name="childModel">

        ///     需要观察的对象(发布方).

        ///     此处用模型基类来传递,是为了兼容所有派生于此模型的观察者,从而提高扩展性.

        /// </param>

        public Mouse(string name,ModelBase childModel):base(childModel)

        {

            //初始化字段(老鼠的名字)

            this.name=name;         

        }

        /**//// <summary>

        /// 覆盖了该类观察者需要作出的具体响应行为.

        /// 此行为已在观察者基类中注册于委托事件,由委托事件调度执行,不需要直接调用.

        /// </summary>

        public override void Response()

        {

            //具体响应内容

            System.Console.WriteLine(this.name+"开始逃跑");

        }

 

    }

}


 

//----------------具体观察者(主人)----------------


 

using System;

 namespace DelegateEvent

{

    /**//// <summary>

    ///     此类为观察者模式中的具体观察者(即具体发布方),其继承于观察者基类.

    /// 其中覆盖了观察者基类规划好的方法,实现了响应的具体行为.

    /// </summary>

    public class Master:Observer

    {

        /**//// <summary>

        ///     构造时确定观察者所需要观察的对象(具体目标),并传递给观察者基类构造器,

        /// 实现响应行为(方法)的订阅.

        /// </summary>

        public Master(ModelBase childModel):base(childModel)

        {

        }

 

        /**//// <summary>

        /// 覆盖了该类观察者需要作出的具体响应行为.

        /// 此行为已在观察者基类中注册于委托事件,由委托事件调度执行,不需要直接调用.

        /// </summary>

        public override void Response()

        {

            System.Console.WriteLine("主人醒来");

        }

    }

}


 

 

//-------------------具体观察者(宝宝)-------------

 

 

using System;

 namespace DelegateEvent

{

    /**//// <summary>

    ///     此类为观察者模式中的具体观察者(即具体发布方),其继承了订阅了2个响应行为的

    /// 观察者基类.

    ///     其中覆盖了观察者基类规划好的二个方法,实现了响应的具体行为.

    /// </summary>

    public class Master2:Observer2

    {

        /**//// <summary>

        ///     构造时确定观察者所需要观察的对象(具体目标),并传递给观察者基类构造器,

        /// 实现响应行为(方法)的订阅.

        /// </summary>

        public Master2(ModelBase childBase):base(childBase)

        {

        }

 

        /**//// <summary>

        /// 覆盖了该类观察者需要作出的具体响应行为.

        /// 此行为已在观察者基类中注册于委托事件,由委托事件调度执行,不需要直接调用.

        /// </summary>

        public override void Response()

        {

            Console.WriteLine("baby醒来。。。。");

 

        }

        /**//// <summary>

        /// 覆盖了该类观察者需要作出的另一个响应行为.

        /// </summary>

        public override void Response2()

        {

            Console.WriteLine("开始哭闹。。。。。");

        }

    }

}


 


5.   运行测试

 

 

 

 using System;
 
  namespace DelegateEvent
 
 {

    /**//// <summary>

    /// Observer Pattern(观察者模式)事例分析

    /// 

    /// 题目:猫大叫,两只老鼠开始逃跑,主人醒来,宝宝也醒来了并且哭了起来.

    /// 

    /// 关于目标(发布方):

    ///     在此事例中,只有一个目标对象(发布方)猫,因为其他全部实体的行为都是

    /// 响应它的"大叫"所执行的.猫是主动方,它的大叫引起一系列的连锁反应.

    /// 

    /// 关于观察者(订阅方):

    ///     至于此事例的中的观察者分别有两大类,一类是听到猫大叫后只作出一种

    /// 反应的观察者(老鼠,主人),另一类是听到锚大叫后会作出两种响应的观察者(

    /// 宝宝).所以观察者分别需要派生于两个不同的观察者基类.

    /// </summary>

    public class SubMain

    {

        public SubMain()

        {

            

        }

        public static void Main()

        {

            //声明并实例化一个目标(即发布方)对象----猫

            Cat myCat=new Cat();

            //声明并实例化一个Mouse类型的观察者对象--名叫mouse1的老鼠.并把那只猫作为它所要观察的对象.

            Mouse myMouse1=new Mouse("mouse1",myCat);

            //类似地生成另一只名叫mouse2的老鼠(观察者),把同一只猫作为它的观察的对象.

            Mouse myMouse2=new Mouse("mouse2",myCat);

            //声明并实例化一个Master类型的观察者--主人,并同时把那只猫也作为他的观察对象.

            Master myMaster=new Master(myCat);

            //声明并实例化一个Master2类型的观察者--宝宝,同时把那只猫也

            Master2 myLittleMaster=new Master2(myCat);

 

            //猫大叫,并触发了委托事件,从而开始按顺序调用观察者已订阅的方法.

            myCat.Cry();

 

            Console.Read();

        }

    }

}

 

 

分享到:
评论

相关推荐

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

    现在,让我们逐步构建这个简单的C#观察者模式实例: 1. **定义委托** 首先,我们需要定义一个委托类型,表示观察者应该执行的操作。例如: ```csharp public delegate void StateChangedEventHandler(object ...

    浅谈观察者模式及在C#中的实现

    在C#中实现观察者模式时,通常会定义两个基本的类:`ModelBase`作为目标的抽象基类,`ObserverBase`作为观察者的抽象基类。这些基类提供了模式的基本结构,以便于具体的目标和观察者类能够方便地实现所需的功能。 1...

    C# 工厂和观察者模式的小工程

    在C#中,`System.ComponentModel.INotifyPropertyChanged`接口是实现观察者模式的一种常见方式,常用于数据绑定场景。当你改变对象的某个属性时,通过触发`PropertyChanged`事件,可以通知所有已订阅的对象。 在这...

    C#观察者模式

    在C#中,观察者模式主要通过事件(Event)和委托(Delegate)机制来实现,这使得对象之间的耦合度降低,提高了代码的可维护性和可扩展性。 首先,我们要理解C#中的事件和委托。委托是C#中的一个类型,它代表方法的...

    委托实现观察者模式

    C#语言提供了一种强大的工具——委托,来实现观察者模式。 委托在C#中类似于函数指针,它能够引用方法,并可以在运行时动态地调用这些方法。委托是类型安全的,可以用来传递方法作为参数,或者将方法存储在变量中。...

    C#不同窗体间的数据传递发布订阅模式(观察者模式)源码范例

    本资源重点探讨的是发布订阅模式(也称为观察者模式)在C#窗体间数据传递的应用。 发布订阅模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到...

    C#中观察者模式的3种实现方式

    在C#中,观察者模式有多种实现方式,包括.NET框架内置的Event模型、使用IObservable和IObserver接口以及Action函数式方案。下面我们将详细介绍这三种实现方式。 1. 利用.NET的Event模型来实现 .NET的Event模型是最...

    观察者模式学习

    除了标准实现,还有很多其他语言和框架提供了观察者模式的支持,例如在C#中,可以使用System.ComponentModel.INotifyPropertyChanged接口来实现,而在JavaScript中,可以通过事件监听器或者发布/订阅模式来实现类似...

    WinForm窗体之间参数传递(委托加事件观察者模式实现)

    实现事件观察者模式** 事件观察者模式包含两个角色:主题(Subject)和观察者(Observer)。在WinForm中,我们的窗体可以扮演这两个角色。创建一个窗体`Form1`作为发布者(Subject),另一个窗体`Form2`作为订阅者...

    C#委托与观察者模式

    ### C#委托与观察者模式 #### 一、引言 在.NET Framework中,委托和事件扮演着极其重要的角色。对于初学者来说,理解和运用这些概念可能会遇到一定的困难。本文旨在通过实例帮助读者掌握委托的基本原理及其在.NET ...

    (行为型模式) Observer 观察者模式

    在.NET框架中,观察者模式通常通过事件(Event)机制来实现。事件机制提供了发布/订阅模型,使得对象间的耦合程度大大降低。在这个模型中: - **事件(Event)**:代表了一个可以被其他对象监听的动作。在C#中,...

    观察这模式气象站检测c#代码实现

    接下来,我们将深入探讨如何在C#中实现观察者模式。 首先,我们需要定义一个主题(Subject)类,它存储了观察者列表,并提供添加、删除观察者的方法。同时,这个类还需要有一个方法来通知所有的观察者,通常通过...

    C#面向对象设计模式纵横谈 12种设计模式

    C#的事件(Event)和委托(Delegate)机制是实现观察者模式的基础。 以上12种设计模式构成了C#面向对象设计的基础框架,理解和熟练运用这些模式可以极大地提升代码的可读性、可维护性和复用性,帮助开发者编写出...

    观察者模式应用

    **实现观察者模式的方法:** 1. **接口实现**:定义Observer和Subject接口,通过实现接口来创建具体的观察者和被观察者对象。 2. **类继承**:使用类继承的方式,被观察者作为基类,提供注册、移除和通知方法,观察...

    设计模式 之 观察者模式

    描述中提到的“事件委托”是一种在Windows窗体应用程序中常见的实现观察者模式的方式,特别是在.NET Framework中。事件委托允许我们创建事件处理程序,并将它们委托给其他对象处理。这样,当一个特定的事件发生时,...

    C#设计模式(PDF+源码)

    3. **观察者模式**:定义对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。C#中的`System.ComponentModel.INotifyPropertyChanged`接口常用于实现此模式。 ```...

    C#设计模式(PDF)

    而委托(Delegate)和事件(Event)机制则天然契合观察者模式,使得异步编程和响应式设计更为便捷。 此外,这本书可能还会涵盖一些现代设计原则和实践,如SOLID原则(单一职责原则、开闭原则、里氏替换原则、接口...

    观察者模式

    此外,结合现代编程语言特性,如C#中的`event`关键字和.NET框架的`EventHandler`委托,或者JavaScript中的事件监听和触发机制,观察者模式的实现更加灵活和高效。虽然本案例中没有具体的源码分析,但理解观察者模式...

    C#23种开发模式实例

    12. 观察者模式(Observer Pattern):定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。C#中,Event和Delegate是实现方式。 13. 模板方法模式...

Global site tag (gtag.js) - Google Analytics