观察者模式探秘

 

观察者模式探秘

 

在面向对象编程中,开发者越来越注重以前的代码的可重用性和可维护性。

设计模式使人们可以更加简单方便地复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。

今天我们来理解一下观察者模式(Observer Patterns)

观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。它完美的将观察者对象和被观察者对象分离。可以在独立的对象(主体)中维护一个对主体感兴趣的依赖项(观察器)列表。让所有观察器各自实现公共的 Observer 接口,以取消主体和依赖性对象之间的直接依赖关系。

例如,有一个邮局(Subject),下属有数个业务员(Delegate),业务员下属又有若干个邮递员(Event),业务员和邮递员之间是1:n的关系,邮递员接受业务员的指示而决定把东西邮递给谁。这样,整个邮局就作为了一个被观察者对象。又有一个杂志社(Observer),为了将杂志(Response方法)邮递给订阅者,必须通过邮局来办理,于是杂志社就找到了邮局的一个业务员,告诉他杂志社要把这本杂志邮递给订阅者,然后业务员把信息转达个他下属的一个邮递员,由邮递员负责把杂志送到指定的订阅者手中。这就是一个典型的观察者模式的例子,其中,邮局是被观察者对象,杂志社则为观察者对象。

再来看另外一个例子,夜里有一只猫大叫了一声,同处一屋的老鼠接受到了猫大叫的信息,于是开始逃跑。同样,主人听到了,被吵醒了;小孩子听到了,被吓哭了。让我们用代码来实现这个例子。

首先,我们来建立观察者模型。被观察者对象可以定义一个抽象基类Subject,这个基类只负责定义委托和事件。

using System;

namespace DelegateEvent

{

    /// <summary>

    /// Subject 的摘要说明。

    /// 被观察者抽象基类

    /// 所有被观察者对象都继承此类

    /// 做为抽象基类,此类不允许直接进行实例化

    /// 此类中首先定义委托

    /// 再有委托定义事件

    /// 然后创立与委托想关联的方法Notify

    /// </summary>

    public abstract class Subject

    {

        public Subject()

        {

            //

            // TODO: 在此处添加构造函数逻辑

            //

        }

        /// <summary>

        /// 创建一个委托

        /// </summary>

        public delegate void SubEventHandler();

        /// <summary>

        /// 根据SubEventHandler创建一个事件

        /// </summary>

        public event SubEventHandler SubEvent;

        /// <summary>

        /// 将于委托相连接的方法

        /// </summary>

        protected void Notify()

        {

            if(this.SubEvent!=null)

                this.SubEvent();

        }

    }

}

//------------------------------------------------------------------------------------------

被观察者基类完成后我们再来创建观察者基类Observer.

namespace DelegateEvent

{

    /// <summary>

    /// Observer 的摘要说明。

    /// 观察者抽象基类

    /// 所有观察者对象都由此类派生

    /// 使用此类进行对事件的注册

    /// 并和事件的方法关联

    /// 另外定义了一个抽象方法Response

    /// 可以由子类来进行覆盖

    /// </summary>

    public abstract class Observer

    {

        public Observer(Subject childModel)

        {

            //注册SubEvent事件通过SubEventHandler委托和Response方法关联

            //子类通过调用此构造函数完成事件的注册

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

        }

 

        /// <summary>

        /// 抽象方法,用于引发事件

        /// </summary>

        public abstract void Response();

    }

}

同理,我们还可以继续创建另一个观察者基类,用来响应不同的事件的方法。

namespace DelegateEvent

{

    /// <summary>

    /// Observer2 的摘要说明。

    /// 注册了两个事件的方法。

    /// </summary>

    public abstract class Observer2

    {

        public Observer2(Subject childModel)

        {

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

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

        }

        public abstract void Response();

        public abstract void Response2();

    }

}

//-------------------------------------------------------------------------------------------------------

现在,我们来针对这个实例中的猫大叫这个引发事件进行解析。

namespace DelegateEvent

{

    /// <summary>

    /// Cat 的摘要说明。

    /// 此类作为被观察者对象

    /// 直接继承Subject

    /// 使用一个Cry方法,调用Notify方法起用先前定义的SubEvent事件

    /// </summary>

    public class Cat:Subject

    {

        public Cat()

        {

            //

            // TODO: 在此处添加构造函数逻辑

            //

        }

        public void Cry()

        {

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

            //调用从ModelBase继承过来的Notify()

            this.Notify();         

        }

    }

}

// 这样一个被观察者对象就完成了。

//--------------------------------------------------------------------------------------------------------------------

被观察者对象有了,我们再来创建具体的观察者对象。此例中,有主人,小孩和老鼠对猫的叫声做出了反应,因此我们可以创建三个类,分别对主人、小孩和老鼠进行响应。其中,主人和老鼠对应Observer类,响应其中的一个事件;而小孩则继承Observer2类,响应其中的两个事件。

//------------------------------------观察者--主人类---------------------------------------------------

namespace DelegateEvent

{

    /// <summary>

    /// Master 的摘要说明。

    /// </summary>

    public class Master:Observer

    {

        /// <summary>

        /// 构造函数,接受一个Cat类型的对象childModel并强制转换为基类ModelBase变量

        /// 再将childModel传入到父类Observer的构造函数当中,实现注册。

        /// </summary>

        /// <param name="childModel"></param>

        public Master(Subject childModel):base(childModel)

        {      

           

        }

        public override void Response()

        {

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

        }

    }

}

//------------------------------------观察者--老鼠类-----------------------------------------------------

namespace DelegateEvent

{

    /// <summary>

    /// Mouse 的摘要说明。

    /// </summary>

    public class Mouse:Observer

    {

        private string name;

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

        {

            this.name=name;        

        }

 

        //覆盖ObserverResponse方法

        public override void Response()

        {

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

        }

    }

}

//于主人类不同的是,老鼠类的构造函数可以接受一个字符串参数,这样可以变的更多样化

//------------------------------------观察者--小孩------------------------------------------------------------

namespace DelegateEvent

{

    /// <summary>

    /// Child 的摘要说明。

    /// </summary>

    public class Child:Observer2

    {

        public Child(Subject childBase):base(childBase)

        {

 

        }

        public override void Response()

        {

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

        }

        public override void Response2()

        {

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

        }

    }

}

//小孩类里,由于继承的是Observer2类,因此可以响应两种不同的方法。

在主函数里,定义每个观察者子类的对象,由其构造函数接受被观察者对象进行事件的响应。

namespace DelegateEvent

{

    /// <summary>

    /// SubMain 的摘要说明。

    /// </summary>

    public class SubMain

    {

        public SubMain()

        {

           

        }

        /// <summary>

        /// 主函数,定义子类对象

        /// </summary>

        public static void Main()

        {

            Cat myCat=new Cat();

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

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

            Master myMaster=new Master(myCat);

           

            Child myLittleMaster=new Child(myCat);

            myCat.Cry();

        }

    }

}

至此,一个简单的观察者模型结束了。

 

posted @ 2005-11-07 20:50  冰隼  阅读(1057)  评论(0编辑  收藏  举报