• Observer Pattern, Delegate and Event


    When we learn the Observer Pattern, we will see the Figure like this:

    It come from the << Head.First.Design.Patterns>>. Let us to learn this pattern together....

    Observer is a abstract class or interface, it define a series of methods. these methods can be executed when the Subject have a notify to happen. Now, i give some code to analyse it:

    namespace ObserverPattern2
    {
        
    class Program
        {
            
    static void Main(string[] args)
            {
                Observer1 o1 
    = new Observer1();
                Observer2 o2 
    = new Observer2();

                Subject subject 
    = new Subject();
                subject.RegisterObserver(o1);
                subject.RegisterObserver(o2);

                subject.Notify(
    "billok");
                subject.Notify(
    "billchen");
                subject.RemoveObserver(o2);
                subject.Notify(
    "cjb");

                Console.ReadLine();
            }
        }

        
    public abstract class Observer
        {
            
    public abstract void Update(string userName);
        }

        
    public class Observer1 : Observer
        {
            
    public override void Update(string userName)
            {
                Console.WriteLine(
    "Update Observer1 " + userName);
            }
        }

        
    public class Observer2 : Observer
        {
            
    public override void Update(string userName)
            {
                Console.WriteLine(
    "Update Observer2 " + userName);
            }
        }

        
    public interface ISubject
        {
            
    void RegisterObserver(Observer observer);//register an Observer
            void RemoveObserver(Observer observer);//remove an Observer
            void Notify(string userName);//notify observers when the state is changed
        }

        
    public class Subject : ISubject
        {
            
    private List<Observer> observers;

            
    public Subject()
            {
                observers 
    = new List<Observer>();
            }

            
    public void RegisterObserver(Observer observer)
            {
                
    if (!observers.Contains(observer))
                    observers.Add(observer);
            }

            
    public void RemoveObserver(Observer observer)
            {
                
    int i = observers.IndexOf(observer);
                
    if (i >= 0)
                    observers.Remove(observer);
            }

            
    public void Notify(string userName)
            {
                
    foreach (Observer observer in observers)
                {
                    observer.Update(userName);
                }
            }
        }
    }

    Observer1 and Observer2 are the implement of abstract Observer. They really finish the Update(string userName) method. This method will be executed when Observer is notified.

    How to notify these Observer? It is Subject's duty. ISubject define three methods(RegisterObserver, RemoveObserver, Notify). RegisterObserver is used to register a new Observer, this observer will be notified when subject's Notify method is executed.
    RemoveObserver is used to remove existent Observer, then it will be not notified.
    Notify is used to tigger an action, this action will be notify all of Observers of the storage of the Subject.

    Now, Subject is a implementing class of the ISubject interface.

    How to use this Observer Pattern to finish our job? First, we can create a Subject object, and create some Observer's implements. Next, you add the objects to the Subject object by RegisterObserver method. Finally, we execute the Notify method, and all of the Observer will be notified and their Update method will be executed.

    Maybe you can take note of my codes is differ from the Figure. In the Figure, ConcreteObserver class have a reference of the ISubject. we can come true it. I think it's duty is simply register itseft to the subject. Let us to add a Isubject reference to the Observer, like this:

        public abstract class Observer
        {
            
    private ISubject iSubject;

            
    private Observer() { }
            
    public Observer(ISubject iSubject)
            {
                
    this.iSubject = iSubject;
                
    this.iSubject.RegisterObserver(this);//register itseft
            }

            
    public abstract void Update(string userName);
        }

    when we new a Observer object, reference of ISubject is added to the new object. Now, we may modify the using of the RegisterObserve. Please look this:

    Subject subject = new Subject();
    Observer1 o1 
    = new Observer1(subject);
    Observer2 o2 
    = new Observer2(subject);
    subject.Notify(
    "billok");

    Okay, i give another version:

    another version


          Okay, Now! Let us take attention to the implement of Observer Pattern in C#.

    We should use the Delegate and Event to implement the Observer Pattern in the .NET Framework. I give the new edition for .net like it:

    namespace ObserverPattern3
    {
        
    class Program
        {
            
    static void Main(string[] args)
            {
                Trigger trigger 
    = new Trigger();
                trigger.Changed 
    += new Trigger.ChangedEventHandler(trigger_Changed);
                trigger.Changed 
    += delegate(object sender, ChangedEventArgs e)
                {
                    Console.WriteLine(
    "delegate Observer: "+e.UserName);
                };
                trigger.Changed 
    += Observer1;
                trigger.Changed 
    += Observer2;

                trigger.Update(
    "billok");
                trigger.Changed 
    -= Observer2;
                trigger.Update(
    "cjb");

                Console.ReadLine();
            }

            
    static void trigger_Changed(object sender, ChangedEventArgs e)
            {
                Console.WriteLine(
    "custom Observer: " + e.UserName);
            }

            
    public static void Observer1(Object sender, ChangedEventArgs e)
            {
                Console.WriteLine(
    "Observer1: " + e.UserName);
            }

            
    public static void Observer2(Object sender, ChangedEventArgs e)
            {
                Console.WriteLine(
    "Observer2: " + e.UserName);
            }
        }


        
    public class ChangedEventArgs : EventArgs
        {
            
    public readonly string UserName;

            
    public ChangedEventArgs(string userName)
            {
                
    this.UserName = userName;
            }
        }

        
    public class Trigger
        {
           
    //declare a delegate variable.
            
    public delegate void ChangedEventHandler(Object sender, ChangedEventArgs e);
            public event ChangedEventHandler Changed;//declare a event.

            
    protected virtual void OnChanged(ChangedEventArgs e)
            {
                
    if (Changed != null)
                {
                    Changed(
    this, e);
                }
            }

            
    public void Update(string userName)
            {
                ChangedEventArgs e 
    = new ChangedEventArgs(userName);
                OnChanged(e);
            }
        }
    }

    You can see i define a Delegate variable and Event variable in the Trigger classs.
    Please notice how to define the event frame.
    attention:

    • The name of Delegate type must end by EventHandler.
    • Definition of Delegate must have "void" return value, and it have two parameters, one is Object type, One is EventArgs type or implement of the EventArgs.
    • The name of Event is remove the "EventHandler" from the name of Delegate.
    • The name of Implement of the EventArgs should end by EventArgs.

    How to register and remove the observer? we can use "+=" and "-=" to do it. please look the source code.

  • 相关阅读:
    剑指Offer——旋转数组的最小数字
    剑指Offer——用两个栈实现队列
    剑指Offer——从尾到头打印链表
    剑指Offer——替换空格
    剑指Offer——二维数组中的查找
    剑指Offer——数据流中的中位数
    剑指Offer——字符流中第一个不重复的字符
    剑指Offer——删除链表中重复的结点
    运维常用shell脚本
    log4cxx的使用
  • 原文地址:https://www.cnblogs.com/chenjunbiao/p/1760168.html
Copyright © 2020-2023  润新知