观察者模式——委托与事件

一、委托与事件

委托是对函数的封装,可以当作给方法的特征指定一个名称。而事件则是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程。

需要注意的是:

委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。比如书上举得例子是老鼠逃跑这件事委托给猫叫只要猫叫就执行老鼠跑的动作。就是委托触发另一个事件的执行。也可以理解成,猫叫是对象A,猫叫是委托B,老鼠跑是方法C。A想调用C的某些方法,但是A和C可能因为某些原因不能直接产生联系,这时候就借助对象B起到桥梁的作用,将A与C连接起来。也很像API函数中的句柄:句柄就像指针指向地址,我们关键的是要这个地址中所存放的东西。通过句柄我们可以取出我们要用的复杂的函数和方法。只不过在委托中这个方法或函数变成了一个事件。

委托用关键字delegate来声明,而事件是说在发生其他类或对象关注的事情时,类或对象可通过事件通知它们,如下面的例子,


 public delegate void CatShoutEventHandler();//声明委托CatShoutEventHandler
            public event CatShoutEventHandler CatShout;//声明事件CatShout,它的事件类型是委托CatShoutEventHandler
 public void Shout()
            {
                Console.WriteLine("喵,我是{0}", name);
                if (CatShout != null)
                {
                    CatShout();//表明当执行Shout()方法时,如果CatShout中有对象登记事件,则执行CatShout()
                }
            }

在主函数中调用

cat.CatShout += new Cat.CatShoutEventHandler(mouse1.Run);
            cat.CatShout += new Cat.CatShoutEventHandler(mouse2.Run);//表示将Mouse的run方法通过实例化委托Cat.CatShoutEventHandler登记到CatShout当中。其中“+=”表示“add_CatShout”的意思

二、观察者模式

观察者模式又叫发布订阅(Publish/Subscribe)模式:它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使他们能够自动更新自己。

                  

先来说说书上举的例子,就是老板回来,通知员工,员工马上各司其职。多个员工同时监听老板,在老板的状态发生改变时,他们立马改变自己的状态,变成认真工作的状态。我们先来抽象一下这个系统有两个大类(抽象类),就是通知者和观察者。

另外要用到这个方法的话,一定是观察者(被通知者)不只一个,要不然也不需要通知者了(要知道,我们使用某个模式只是因为这个模式更方便),所以通知者那里应该有一份名单,知道自己要通知谁,而且随时可以添加或删除人员。(有没有觉得我们敲机房的添加删除卡号很适合这个模式微笑,以后可以试一下)所以有如下的代码

   //抽象通知者接口
        interface Subject
        {
            void Attach(Observer observer);
            void Detach(Observer observer);
            void Notify();
            string SubjectState
            {
                get ;
                set;
            }
        }
然后实例化
 //老板其实也是通知者
        class Boss : Subject
        { 
            //同事列表
            private IList<Observer> observers = new List<Observer>();
            private string action;
            //增加
            public void Attach(Observer observer)//针对抽象编程,减少了与具体类的耦合
            {
                observers.Add(observer);

            }
            //减少
            public void Detach(Observer observer)//针对抽象编程,减少了与具体类的耦合
            {
                observers.Remove(observer);
            }
            //通知
            public void Notify()
            {
                foreach (Observer o in observers)//待老板来时,就给所有的登记的同事们发通知,“老板来了”
                    o.Update();
            }
            //老板状态
            public string SubjectState//前台的行动
            {
                get { return action; }
                set { action = value; }

            }
        }



这个例子也很适合用委托和事件来实现。是老板回来的事件,触发员工的各种行为。

class Program
    {
        static void Main(string[] args)
        {
        //老板胡汉三
        Boss huhansan = new Boss();

        //看股票的同事
        StockObserver tongshi1 = new StockObserver("魏关宅", huhansan);
        //看NBA的同事
        NBAObserver tongshi2 = new NBAObserver("易管查", huhansan);

        huhansan.Update += new EventHandler(tongshi1.CloseStokMarket);
        huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding);

            //老板回来
        huhansan.SubjectState = "我胡汉三回来了!";
            //发出通知
        huhansan.Notify();

        }
        //看股票的同事
        class StockObserver
        {
            private string name;
            private Subject sub;
            public StockObserver(string name, Subject sub)
            {
                this.name = name;
                this.sub = sub;                             
            }
            //关闭股票行情
            public void CloseStokMarket()
            {
                Console.WriteLine("{0}{1}关闭股票行情,继续工作!", sub.SubjectState, name);

            }

        }
        //看NBA的同事
        class NBAObserver
        {
            private string name;
            private Subject sub;
            public NBAObserver(String name, Subject sub)
            {
                this.name = name;
                this.sub = sub;
            }
            //关闭NBA直播
            public void CloseNBADirectSeeding()
            {
                Console.WriteLine("{0}{1}关闭NBA直播,继续工作!", sub.SubjectState, name);
            }
        }
        //通知者接口
        interface Subject
        {
            void Notify();
            string SubjectState
            {
                get;
                set;
            }
        }
        delegate void EventHandler();
        class Boss: Subject
        { 
            //声明一事件Update,类型为委托EventHandler
            public event EventHandler Update;

            private string action;

            public void Notify()
            {
                Update();
            }
            public string SubjectState
            {
                get { return action; }
                set { action = value; }
            }
        }
       
    }

总结:当一个对象的改变需要同时改变其他对象而且它不知道具体有多少对象有待改变时,很适合使用观察者模式。当一个抽象模型有两个方面,其中一个方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立的改变和复用。总的来说,观察者所做的工作就是在解除耦合。让耦合的双方都依赖于抽象而不是具体。从而使得各自的变化都不会影响另一边的变化。套用合适的设计模式可以解决很多我们用编码不能解决的问题,所以从现在起就让我们养成用设计模式的习惯吧!

猜你喜欢

转载自blog.csdn.net/u013034828/article/details/41928735