如何使对象功能的扩展能够根据需要来动态(即运行时)地实现?同时避免扩展功能的增多带来的子类膨胀问题?从而使得任何功能扩展

时间:2021-08-25 08:55:32

一、引言

   今天我们要讲【布局型】设计模式的第三个模式,该模式是【装饰模式】。我第一次看到这个名称想到的是此外一个词语“装修”,我就说说我对“装修”的理解吧,大家必然要看清楚,是“装修”,不是“装饰”。我们长大了,就要成婚,要成婚就涉及到要买屋子,买的精装修或者简单装修就可以住的,暂时不谈。我们就谈谈我们采办的是毛坯房。如果我想要屋子的内饰是大理石气势派头的,我们只要在毛坯房的根本之上用大理石气势派头的质料装修就可以,我们固然不成能为了要一个装修气势派头,就把刚刚盖好的屋子拆了在从头来过。屋子装修好了,我们就住了进来,很高兴。过了段时间,我们发明我们的屋子在冬季对照冷,于是我就想给我们的屋子增加保暖的成果,装修好的屋子我们可以继续居住,我们只是在屋子外面加一层掩护层就可以了。又过了一段时间,总是有陌生人帮衬,所以我们想让屋子更安适,于是我们在外墙和房顶加装安适摄像头,同时门窗也增加安适系统。跟着时间的流逝,我们可能会按照我们的需求增加相应的成果,期间,我们的屋子可以正常使用,加上什么设施就有了相应的成果。从这一方面来讲,“装修”和“装饰”有类似的观点,接下来就让我们看看装饰模式具体是什么吧!

二、装饰模式的详细介绍

2.1、动机(Motivate)

   在屋子装修的过程中,各类成果可以彼此组合,来增加屋子的服从。类似的,如果我们在软件系统中,要给某个类型或者东西增加成果,,如果使用“担任”的方案来写代码,就会呈现子类暴涨的情况。好比:IMarbleStyle是大理石气势派头的一个成果,IKeepWarm是保温的一个接口界说,IHouseSecurity是屋子安适的一个接口,就三个接口来说,House是我们屋子,我们的屋子要什么成果就实现什么接口,如果屋子要的是复合成果,接口差此外组合就有差此外功效,这样就导致我们子类膨胀严重,如果需要在增加成果,子类会成指数增长。这个问题的泉源在于我们“过度地使用了担任来扩展东西的成果”,由于担任为类型引入的静态特质(所谓静态特质,就是说如果想要某种成果,我们必需在编译的时候就要界说这个类,这也是强类型语言的特点。静态,就是指在编译的时候要确定的对象;动态,是指运行时确定的对象),使得这种扩展方法缺乏灵活性;并且跟着子类的增多(扩展成果的增多),各类子类的组合(扩展成果的组合)会导致更多子类的膨胀(多担任)。如何使“东西成果的扩展”能够按照需要来动态(即运行时)地实现?同时制止“扩展成果的增多”带来的子类膨胀问题?从而使得任何“成果扩展变革”所导致的影响降为最低?

2.2、意图(Intent)

   动态地给一个东西增加一些特别的职责。就增加成果而言,Decorator模式比生成子类更为灵活。         ——  《设计模式》GoF

2.3、布局图

      

如何使对象功能的扩展能够根据需要来动态(即运行时)地实现?同时避免扩展功能的增多带来的子类膨胀问题?从而使得任何功能扩展



2.4、模式的构成

    在装饰模式中的各个角色有:

  . 抽象构件(Component)角色:给出一个抽象接口,以规范筹备接收附加责任的东西。

  . 具体构件(Concrete Component)角色:界说一个将要接收附加责任的类。

  . 装饰(Decorator)角色:持有一个构件(Component)东西的实例,并实现一个与抽象构件接口一致的接口。

  . 具体装饰(Concrete Decorator)角色:卖力给构件东西添加上附加的责任。

2.5 、装饰模式的具体实现

   刚开始一看这个“装饰模式”是有点不太好理解,既然这个模式是面向东西的设计模式,那在现实生活中必然有事例和其对应,其实这种例子也不少,大家好好的挖掘吧,也可以提高我们劈面向东西的理解。我继续拿盖屋子来说事吧。
   

1 namespace 装饰模式的实现 2 { 3 /// <summary> 4 /// 该抽象类就是屋子抽象接口的界说,该类型就相当于是Component类型,是饺子馅,需要装饰的,需要包装的 5 /// </summary> 6 public abstract class House 7 { 8 //屋子的装修要领--该操纵相当于Component类型的Operation要领 9 public abstract void Renovation(); 10 } 11 12 /// <summary> 13 /// 该抽象类就是装饰接口的界说,该类型就相当于是Decorator类型,如果需要具体的成果,可以子类化该类型 14 /// </summary> 15 public abstract class DecorationStrategy:House //关键点之二,浮现关系为Is-a,有这这个关系,装饰的类也可以继续装饰了 16 { 17 //通过组合方法引用Decorator类型,该类型实施具体成果的增加 18 //这是关键点之一,包罗关系,浮现为Has-a 19 private House _house; 20 21 //通过结构器注入,初始化平台实现 22 protected Database(House house) 23 { 24 this.__house=house; 25 } 26 27 //该要领就相当于Decorator类型的Operation要领 28 public abstract void Process(); 29 } 30 31 /// <summary> 32 /// PatrickLiu的屋子,我要按我的要求做屋子,相当于ConcreteComponent类型,这就是我们具体的饺子馅,我小我私家对照喜欢韭菜馅 33 /// </summary> 34 public class PatrickLiuHouse:House 35 { 36 public override void Renovation() 37 { 38 Console.WriteLine("PatrickLiu的屋子"); 39 } 40 } 41 42 43 /// <summary> 44 /// 具有安适成果的设备,可以供给监视和报警成果,相当于ConcreteDecoratorA类型 45 /// </summary> 46 public class HouseSecurityDecorator:DecorationStrategy 47 { 48 public override void Process() 49 { 50 Console.WriteLine("增加安适系统"); 51 } 52 } 53 54 /// <summary> 55 /// 具有保温接口的质料,供给保温成果,相当于ConcreteDecoratorB类型 56 /// </summary> 57 public sealed class KeepWarmDecorator:DecorationStrategy 58 { 59 public override void Process() 60 { 61 Console.WriteLine("增加保温的成果"); 62 } 63 } 64 65 public class Program 66 { 67 static void Main() 68 { 69 //这就是我们的饺子馅,需要装饰的屋子 70 House myselfHouse=new PatrickLiuHouse(); 71 72 DecorationStrategy securityHouse=new HouseSecurityDecorator(myselfHouse); 73 securityHouse.Process(); 74 //屋子就有了安适系统了 75 76 //如果我既要安适系统又要保暖呢,继续装饰就行 77 DecorationStrategy securityAndWarmHouse=new HouseSecurityDecorator(securityHouse); 78 securityAndWarmHouse.Process(); 79 } 80 } 81 }