zoukankan      html  css  js  c++  java
  • 艾伟_转载:把委托说透(4):委托与设计模式 狼人:

    委托与很多设计模式都有着千丝万缕的联系,在前面的随笔中已经介绍了委托与策略模式的联系,本节主要来讨论委托与其他两个模式:观察者模式和模板方法模式。

    委托与观察者模式

    在.NET中,很多设计模式得到了广泛应用,如foreach关键字实现了迭代器模式。同样的,.NET中也内置了观察者模式的实现方式,这种方式就是委托。

    观察者模式的一般实现

    网上可以找到很多资料介绍观察者模式的实现,我这里介绍一种简单的退化后的观察者模式,即Subject类为具体类,在其之上不再进行抽象。

    public class Subject
    {
        private List<Observer> observers = new List<Observer>();
        private string state;
        public string State
        {
            set
            {
                state = value;
                NotifyObservers();
            }
            get { return state; }
        }
        public void RegisterObserver(Observer ob)
        {
            observers.Add(ob);
        }
        public void RemoveObserver(Observer ob)
        {
            observers.Remove(ob);
        }
        public void NotifyObservers()
        {
            foreach (Observer ob in observers)
                ob.Update(this);
        }
    }
    public abstract class Observer
    {
        public abstract void Update(Subject subject);
    }
    public class ConsoleObserver : Observer
    {
        public ConsoleObserver(Subject subject)
        {
            subject.RegisterObserver(this);
        }
        public override void Update(Subject subject)
        {
            Console.WriteLine("Subject has changed its state : " + subject.State);
        }
    }

    调用的方法很简单:

    Subject subject = new Subject();
    Observer observer = new ConsoleObserver(subject);
    subject.State = "Kirin Yao";

    Subject类维护一个列表,负责观察者的注册和移除。当其状态发生改变时,就调用NotifyObservers方法通知各个观察者。

    观察者模式的委托实现

    在.NET中,使用委托可以更简单更优雅地实现观察者模式。在上一篇随笔中,最后的示例其实就是一个观察者模式。MainForm为Subject,SubForm为Observer。当MainForm的状态发生改变时(即点击“传值”按钮时),SubForm作为观察者响应来自MainForm的变化。

    与上例对应的,用委托实现的观察者模式的代码大致如下:

    namespace DelegateSample
    {
        class UpdateEventArgs : EventArgs { }
        class Subject
        {
            private string state;
            public string State 
            {
                get { return state; }
                set 
                {
                    state = value;
                    OnUpdate(new UpdateEventArgs());
                }
            }
            public event EventHandler<UpdateEventArgs> Update;
            public void ChangeState(string state)
            {
                this.State = state;
                OnUpdate(new UpdateEventArgs());
            }
            private void OnUpdate(UpdateEventArgs e)
            {
                EventHandler<UpdateEventArgs> handler = Update;
                if (handler != null)
                    Update(this, e);
            }
        }
        abstract class Observer
        {
            public Subject Subject { get; set; }
            public Observer(Subject subject)
            {
                this.Subject = subject;
                this.Subject.Update += new EventHandler<UpdateEventArgs>(Subject_Update);
            }
            protected abstract void Subject_Update(object sender, UpdateEventArgs e);
        }
        class ConsoleObserver : Observer
        {
            public ConsoleObserver(Subject subject) : base(subject) { }
            protected override void Subject_Update(object sender, UpdateEventArgs e)
            {
                Subject subject = sender as Subject;
                if (subject != null)
                    Console.WriteLine("Subject has changed its state : " + subject.State);
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Subject subject = new Subject();
                Observer ob = new ConsoleObserver(subject);
                subject.State = "Kirin Yao";
                Console.ReadLine();
            }
        }
    }

    相比传统的观察者模式的实现方式(在Subject中维护一个Observer列表),使用委托避免了Subject与Observer之间的双向引用,Subject作为主题类,对观察者毫无所知,降低了耦合性,语法上也更加优雅。

    委托与模板方法模式

    模板方法模式封装了一段通用的逻辑,将逻辑中的特定部分交给子类实现。

    public abstract class AbstractClass
    {
        public void Arithmetic()
        {
            SubArithmeticA();
            SubArithmeticB();
            SubArithmeticC();
        }
        protected abstract void SubArithmeticA();
        protected abstract void SubArithmeticB();
        protected abstract void SubArithmeticC();
    }
    public class ConcreteClass : AbstractClass
    {
        protected override void SubArithmeticA()
        {
            //...
        }
        protected override void SubArithmeticB()
        {
            //...
        }
        protected override void SubArithmeticC()
        {
            //...
        }
    }

    然而这种继承方式的模板方法耦合度较高,特别是如果逻辑与其外部实现没有必然的从属关系的时候,用传统的模板方法就显得不那么合适了。

    在某种程度上,委托可以看做是一个轻量级的模板方法实现方式,它将逻辑中的特定部分转交给注册到委托的方法来实现。从而替代了继承方式的模板方法模式中,在子类中实现特定逻辑的方式。

    public delegate void SubArithmetic();
    public class ConcreteClass
    {
        public void Arithmetic()
        {
            if (SubArithmetic != null)
                SubArithmetic();
        }
        public SubArithmetic SubArithmetic { get; set; }
    }

    而SubArithmetic的实现交给外部:

    ConcreteClass concrete = new ConcreteClass();
    concrete.SubArithmetic = Program.SomeMethod;
    concrete.Arithmetic();

    咋一看在客户端中编写委托的方法似乎还略显麻烦,但值得注意的是,匿名方法和Lambda表达式为我们提供了更加简便的委托语法。在函数式编程日益盛行的今天,我们应该为.NET提供的这种语言特性而感到庆幸。

  • 相关阅读:
    windows下phpunit installing[转]
    一个简单的文件后缀获取——不是通过文件名,而是文件内容
    二进制加法
    收藏一个韩国棒子的未知高度居中方法
    带超时+POST/GET方式的获取远程文件,利用file_get_contents
    较深度地递归转义过滤
    利用单元测试在每个层上对 PHP 代码进行检查[转IBM]
    提取TP的一个格式化为json的针对的原始类型函数
    分享一个正则方式的UTF8/GBK中文切割
    NewBaldwinFlash的登场(稍简单的DNN模块)
  • 原文地址:https://www.cnblogs.com/waw/p/2157132.html
Copyright © 2011-2022 走看看