.NET简谈设计模式之(装饰者模式性能问题?)

来源:互联网 发布:淘宝卖家怎么回评买家 编辑:程序博客网 时间:2024/05/01 16:29
 我假设看这篇文章的朋友对装饰者模式都能有各自的、深入的理解。因为这篇文章是讨论装饰者模式的性能问题。

在本人的“.NET简谈设计模式之(装饰者模式)”一文中比较详细的讲解了装饰者模式的一般应用,但是我总是感觉装饰者模式隐隐约约之中有点不完美。经过我昨天一整天的思考、推敲终于找到了它隐隐约约中的那点不完美是什么,为了行为去继承带来的无辜的性能开销。所以本人想把它写出来,跟大家讨论下装饰者模式的性能该如何平衡。是用时间换空间还是用空间换时间,这里的时间就是我们开发的效率时间。

首先回顾一下装饰者模式诞生的本意是什么,它的官方意思是:动态地给一个对象添加一些额外的职责。我们都知道给对象扩展功能是通过继承来实现,但是继承有它的不好之处,比如:子类与父类之间的耦合、子类的无限扩大等等。而装饰者模式就是想利用动态的给需要扩展的对象添加功能。将需要扩展的动能独立起来,作为一个个装饰类,在需要的时候给对象穿上这个装饰。

1:

 

这张类图照这个样子发展下去不得了,子类无限膨胀,后面需求谁都不知道。这是我们一般扩展对象的正常方法,我们来看一下装饰者模式的原型。

2:

 

将需要扩展的功能独立起来,当需要的时候动态的添加功能。我想这就是装饰者名称由来,将后期扩展的功能比喻成装饰者,是很形象。

但是当我们带着这张图的原理去看代码的时候,它的结构根本不是这样的“干净”。所以说理论与实践是分不开的。请看代码:

using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication2{    public class ConcreteConpontent    {        public virtual void Operation()        {            Console.WriteLine("顶级待装饰对象");        }        public virtual void Message()        {            Console.WriteLine("顶级对象消息");        }    }    public abstract class Decorator : ConcreteConpontent    {        protected ConcreteConpontent m_compontent;        public void SetCompontent(ConcreteConpontent com)        {            m_compontent = com;        }    }    public class ConcreteDecoratorA : Decorator    {        public override void Operation()        {            m_compontent.Operation();            Console.WriteLine("ConcreteDecoratorA进行了方法的动态添加");        }        public override void Message()        {            m_compontent.Message();            Console.WriteLine("ConcreteDecoratorA进行了Message方法的动态添加");        }    }    public class ConcreteDecoratorB : Decorator    {        public override void Operation()        {            m_compontent.Operation();            Console.WriteLine("ConcreteDecoratorB进行了方法的装饰");        }        public override void Message()        {            m_compontent.Message();            Console.WriteLine("ConcreteDecoratorB进行了Message方法的动态添加");        }    }    public class ConcreteDecoratorC : Decorator    {        public override void Operation()        {            m_compontent.Operation();            Console.WriteLine("ConcreteDecoratorC进行了方法的装饰");        }        public override void Message()        {            m_compontent.Message();            Console.WriteLine("ConcreteDecoratorC进行了Message方法的动态添加");        }    }}

装饰者模式的基本代码原型差不多就这样子的。当我看到装饰者模式是这样的一个代码结构的时候,其实说心里话我难受。里面不是带着继承吗?为什么要继承,心理面不忍发了点牢骚。ConcreteConpontent是被装饰者对象,首先我们要确定要扩展的对象是可以让我们扩展的。其实我知道继承是为了拿到要扩展对象的行为,并且标示所有的装饰者是属于一种类型的,在使用的时候就可以用基类来使用所有的装饰者。如果没有继承显然是不能用基类进行统一调用的,继承还有一个作用就是为了拿到被装饰者的行为,用它的为操作不同的实例,是够聪明的。

我假如我不需要用基类进行统一调用装饰者,我是否就可以不继承自被装饰者了;为了能够实现装饰者的无限递增的装饰,我对代码进行了简单的修改,请看代码:

using System;namespace ConsoleApplication1{    public class ConcreteConpontent    {        public virtual void Operation()        {            Console.WriteLine("顶级待装饰对象");        }        public virtual void message()        {            Console.WriteLine("顶级对象消息");        }    }    public abstract class Decorator    {        private ConcreteConpontent m_compontent;        protected Decorator decorator;        public void SetCompontent(ConcreteConpontent com, Decorator de)        {            m_compontent = com;            decorator = de;        }        public void SetCompontent(ConcreteConpontent com)        {            m_compontent = com;        }        public virtual void Operation()        {            if (decorator != null)                decorator.Operation();            else                m_compontent.Operation();        }        public virtual void message()        {            if (decorator != null)                decorator.message();            else                m_compontent.message();        }    }    public class ConcreteDecoratorA : Decorator    {        public override void Operation()        {            base.Operation();            Console.WriteLine("ConcreteDecoratorA进行了方法的装饰");        }        public override void message()        {            base.message();            Console.WriteLine("ConcreteDecoratorA进行了message方法的动态添加");        }    }    public class ConcreteDecoratorB : Decorator    {        public override void Operation()        {            base.Operation();            Console.WriteLine("ConcreteDecoratorB进行了方法的装饰");        }        public override void message()        {            base.message();            Console.WriteLine("ConcreteDecoratorB进行了message方法的动态添加");        }    }    public class ConcreteDecoratorC : Decorator    {        public override void Operation()        {            base.Operation();            Console.WriteLine("ConcreteDecoratorC进行了方法的装饰");        }        public override void message()        {            base.message();            Console.WriteLine("ConcreteDecoratorC进行了message方法的动态添加");        }    }}

如果我们这是想扩展一个简单的小功能,让我们继承一个很大的对象是不是有点不划算。只是想用被装饰者的行为,去操作装饰者原型实例。我们可以牺牲一下代码的冗余来解决这个性能问题。书上对继承的解释是用来避免手动输入被装饰者的行为代码。我觉得这点根本没有说服力。其实装饰者模式是想动态的给对象添加功能、行为、职责。在使用的时候还是想通过被装饰者进行引用所有的装饰者实例,这样才是继承最有效的说服力。不继承我一样可以有同样的行为、一样可以实现无限递增的嵌套装饰者实例。要想实例套实例,那么他们必须来自同一个祖先,同样是装饰者,要想让装饰者套装饰者,那么在装饰者的类中需要有一个对装饰者类型的引用,但是每一个装饰者不可能一样。所以必须让他们继承同一个基类才行,后面再多的装饰者只要继承同一个基类那么就可以互相引用。