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

简介:

我假设看这篇文章的朋友对装饰者模式都能有各自的、深入的理解。因为这篇文章是讨论装饰者模式的性能问题。

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

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

1:

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

2:

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

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


 
 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4.  
  5. namespace ConsoleApplication2  
  6. {  
  7.     public class ConcreteConpontent  
  8.     {  
  9.         public virtual void Operation()  
  10.         {  
  11.             Console.WriteLine("顶级待装饰对象");  
  12.         }  
  13.         public virtual void Message()  
  14.         {  
  15.             Console.WriteLine("顶级对象消息");  
  16.         }  
  17.     }  
  18.  
  19.     public abstract class Decorator : ConcreteConpontent  
  20.     {  
  21.         protected ConcreteConpontent m_compontent;  
  22.         public void SetCompontent(ConcreteConpontent com)  
  23.         {  
  24.             m_compontent = com;  
  25.         }  
  26.     }  
  27.     public class ConcreteDecoratorA : Decorator  
  28.     {  
  29.         public override void Operation()  
  30.         {  
  31.             m_compontent.Operation();  
  32.             Console.WriteLine("ConcreteDecoratorA进行了方法的动态添加");  
  33.         }  
  34.         public override void Message()  
  35.         {  
  36.             m_compontent.Message();  
  37.             Console.WriteLine("ConcreteDecoratorA进行了Message方法的动态添加");  
  38.         }  
  39.     }  
  40.     public class ConcreteDecoratorB : Decorator  
  41.     {  
  42.         public override void Operation()  
  43.         {  
  44.             m_compontent.Operation();  
  45.             Console.WriteLine("ConcreteDecoratorB进行了方法的装饰");  
  46.         }  
  47.         public override void Message()  
  48.         {  
  49.             m_compontent.Message();  
  50.             Console.WriteLine("ConcreteDecoratorB进行了Message方法的动态添加");  
  51.         }  
  52.     }  
  53.     public class ConcreteDecoratorC : Decorator  
  54.     {  
  55.         public override void Operation()  
  56.         {  
  57.             m_compontent.Operation();  
  58.             Console.WriteLine("ConcreteDecoratorC进行了方法的装饰");  
  59.         }  
  60.         public override void Message()  
  61.         {  
  62.             m_compontent.Message();  
  63.             Console.WriteLine("ConcreteDecoratorC进行了Message方法的动态添加");  
  64.         }  
  65.     }  

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

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


 
 
  1. using System;  
  2.  
  3. namespace ConsoleApplication1  
  4. {  
  5.     public class ConcreteConpontent  
  6.     {  
  7.         public virtual void Operation()  
  8.         {  
  9.             Console.WriteLine("顶级待装饰对象");  
  10.         }  
  11.         public virtual void message()  
  12.         {  
  13.             Console.WriteLine("顶级对象消息");  
  14.         }  
  15.     }  
  16.  
  17.     public abstract class Decorator  
  18.     {  
  19.         private ConcreteConpontent m_compontent;  
  20.         protected Decorator decorator;  
  21.         public void SetCompontent(ConcreteConpontent com, Decorator de)  
  22.         {  
  23.             m_compontent = com;  
  24.             decorator = de;  
  25.         }  
  26.         public void SetCompontent(ConcreteConpontent com)  
  27.         {  
  28.             m_compontent = com;  
  29.         }  
  30.         public virtual void Operation()  
  31.         {  
  32.             if (decorator != null)  
  33.                 decorator.Operation();  
  34.             else 
  35.                 m_compontent.Operation();  
  36.         }  
  37.         public virtual void message()  
  38.         {  
  39.             if (decorator != null)  
  40.                 decorator.message();  
  41.             else 
  42.                 m_compontent.message();  
  43.         }  
  44.     }  
  45.     public class ConcreteDecoratorA : Decorator  
  46.     {  
  47.         public override void Operation()  
  48.         {  
  49.             base.Operation();  
  50.             Console.WriteLine("ConcreteDecoratorA进行了方法的装饰");  
  51.         }  
  52.         public override void message()  
  53.         {  
  54.             base.message();  
  55.             Console.WriteLine("ConcreteDecoratorA进行了message方法的动态添加");  
  56.         }  
  57.     }  
  58.  
  59.     public class ConcreteDecoratorB : Decorator  
  60.     {  
  61.         public override void Operation()  
  62.         {  
  63.             base.Operation();  
  64.             Console.WriteLine("ConcreteDecoratorB进行了方法的装饰");  
  65.         }  
  66.         public override void message()  
  67.         {  
  68.             base.message();  
  69.             Console.WriteLine("ConcreteDecoratorB进行了message方法的动态添加");  
  70.         }  
  71.     }  
  72.     public class ConcreteDecoratorC : Decorator  
  73.     {  
  74.         public override void Operation()  
  75.         {  
  76.             base.Operation();  
  77.             Console.WriteLine("ConcreteDecoratorC进行了方法的装饰");  
  78.         }  
  79.         public override void message()  
  80.         {  
  81.             base.message();  
  82.             Console.WriteLine("ConcreteDecoratorC进行了message方法的动态添加");  
  83.         }  
  84.     }  

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

总结:在我们选择使用装饰者模式的时候,需要根据自己的使用情况进行适当修改。在没有必要的情况下不需要继承那么大的一个对象。





 本文转自 王清培 51CTO博客,原文链接:http://blog.51cto.com/wangqingpei557/622150,如需转载请自行联系原作者



相关文章
|
15天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
61 13
|
17天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
33 2
|
23天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
|
4月前
|
SQL 缓存 开发框架
分享一个 .NET EF6 应用二级缓存提高性能的方法
分享一个 .NET EF6 应用二级缓存提高性能的方法
|
1月前
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
24 5
|
1月前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
32 4
|
1月前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
34 3
|
1月前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
30 3
|
1月前
|
设计模式 Java Kotlin
Kotlin - 改良设计模式 - 装饰者模式
Kotlin - 改良设计模式 - 装饰者模式
28 4
|
1月前
|
人工智能 Java 编译器
.NET 9 发布 性能提升、AI 支持与全方位改进
【11月更文挑战第5天】.NET 9 引入了多项改进,包括性能提升、AI 支持和全方位功能优化。性能方面,编译器增强、服务器 GC 优化、矢量化和硬件支持等提升了执行效率。AI 方面,新增学习材料、合作伙伴生态、原生支持和生成式 AI 集成。此外,.NET Aspire 组件升级、编程语言新功能和开发工具更新进一步提升了开发体验。
下一篇
DataWorks