博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式---装饰模式(Decorator)
阅读量:7217 次
发布时间:2019-06-29

本文共 2480 字,大约阅读时间需要 8 分钟。

 装饰模式是为已有功能动态地添加更多功能的一种模式。当系统需要新功能时,一般做法是向旧的类中添加新的代码,这些新加的代码通常影响了原有类的核心职责或行为,在主类中加入新的字段、方法或是逻辑,从而增加了主类的复杂性,而这些新加入的代码仅仅是为了满足一些只在某种特定情况下才会发生的特殊行为的需要。装饰模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所有要装饰的对象,这样当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择性地,按顺序的使用装饰功能包装的对象了。

      装饰模式在现实生活中随处可见。比如我们买了一辆车,然后我们第一件要做的事,就是把自己的爱车装饰一下。可供选择的配件包括ABS刹车防抱死系统,车载音响,倒车雷达等等,可以选择其中的一件或是多件来装饰我们的爱车。把上述场景转化为程序如下:

有一个MyCarDecorate类,就是一辆裸车。要实现对裸车的装饰,有如下两种方法:

1.在MyCarDecorate里面添加相应的方法。这种做法显然不对。一来违反了面向对象的开放-封闭原则,二来也不易扩展。试想一下,如果每个用户都有不同的需求,那你这个类不是每次调用前都要修改一次吗?

2.使用子类继承的方法。比如用户需要裸车+倒车雷达,则添加一个新类Radar,继承MyCarDecorate;如果用户需要裸车+雷达+音响,则再新加一个Audio类,继承Radar;如果用户只需要裸车+音响,则还需要添加一个新类AudioOnly类,继承自MyCarDecorate…………。看似好像解决了问题,但如果配件有上百种,那么你的子类数量就会呈指数形式增长。所以这种做法也不可取。

 

下面就用本节的主角,装饰模式来解决这个难题吧。为了把车内装饰同车本身分离开,我们要用到一个Show接口,定义如下:public interface ICarShowHandle    {        void Show();    }MyCarDecorate裸车类继承ICarShowHandle接口 public class MyCarDecorate : ICarShowHandle    {        private string _carName;         public MyCarDecorate() { }        public MyCarDecorate(string carName)        {            this._carName = carName;        }         public void Show()        {            Console.WriteLine(string.Format("这就是我的{0}小车", _carName));        }    }为了把裸车的代码同装饰分离,我们需要一个汽车装饰的基类,同样需要继承自ICarShowHandle public class CarTrim : ICarShowHandle    {        private ICarShowHandle _myCar;         public CarTrim(ICarShowHandle myCar)        {            this._myCar = myCar;        }         public virtual void Show()        {            if (_myCar != null)                _myCar.Show();        }    }下面就是让各种装饰一一继承上面这个汽车装饰类。 public class CarRadar : CarTrim    {        public CarRadar(ICarShowHandle myCar) : base(myCar) { }         public override void Show()        {            Console.WriteLine("具有倒车雷达的功能");            base.Show();        }    }public class CarAudio : CarTrim    {        public CarAudio(ICarShowHandle myCar) : base(myCar) { }         public override void Show()        {            Console.WriteLine("具有车载音响系统");            base.Show();        }    }public class CarABS:CarTrim    {        public CarABS(ICarShowHandle myCar) : base(myCar) { }         public override void Show()        {            Console.WriteLine("具有ABS刹车防抱死系统");            base.Show();        }    }

调用方法如下:

1.ICarShowHandle myCar = new CarABS(new CarRadar(new CarAudio(new MyCarDecorate("飞度"))));    myCar.Show();

显示结果为:

装饰模式图片1

2.ICarShowHandle myCar = new CarABS(new CarRadar(new MyCarDecorate("宝马")));    myCar.Show();

显示结果为:

装饰模式图片2

 

 

如需转载,请注明本文原创自CSDN TJVictor专栏:

你可能感兴趣的文章
RabbitMq、ActiveMq、Kafka和Redis做Mq对比
查看>>
C# 图片处理(压缩、剪裁,转换,优化)
查看>>
Linux bridge-utils tunctl 使用
查看>>
Leetcode Pascal's Triangle II
查看>>
运行shell脚本报错 '\357\273\277': command not found 解决的方法
查看>>
android studio 0.8.1使用和遇到问题解决
查看>>
云服务器ECS选购集锦之六区域选择帮助
查看>>
云虚机选购指南之二云虚拟主机试用帮助文档
查看>>
女友眼中的IT男
查看>>
Excel连接
查看>>
java基础-多线程学习
查看>>
WPF打印原理,自定义打印
查看>>
HTML5 5
查看>>
箭头css
查看>>
Python入门,以及简单爬取网页文本内容
查看>>
顺丰科技笔试回忆
查看>>
excel技巧
查看>>
通用防SQL注入漏洞程序(Global.asax方式)
查看>>
服务器进程为何通常fork()两次
查看>>
python中的logger模块
查看>>