现在国内越来越多的城市普及了数字电视,机顶盒也作为一名新成员走进了千家万户,在这里,我将借用机顶盒的例子来描述一下装饰模式。
当您坐在家里,用程序设计的眼光环视四周的时候,通常您这样认为:电视机、电冰箱、电风扇等都是“家用电器”这个类的子类。我们的确可以这样抽象,但我要说的不是这样抽象是否存在不合理性,而是说,如果您所在的小区开始普及数字电视,您必须给电视安装上机顶盒才可以接收到数字电视频道,您会怎么考虑呢?
因为在最初设计您的电视机这个类和生产您的电视机这个实例时,并没有考虑到将来会有机顶盒这种东西,也就不可能把机顶盒的功能集成到电视机这个类里面去。如果说现在重新设计电视机这个类以添加新的功能,那么别的继承自该电视机类的具体电视机类是否也一定要附带这样的功能呢?可想而知,并不是每一种电视机都需要这种功能,所以这样的重新设计费力不讨好,并且增大了成本开销,意味着你必须重新创建你的电视机实例,说白了就是去商店重新买一台。
那么将来有一天如果数字电视不流行了,或者你发觉在家看电视的时间非常少,完全没有必要浪费钱,索性不要机顶盒而只收看仅有的几个传统电视频道,少是少了点儿,但也能满足你的需要,那么你完全可以直接拿走机顶盒就行了。但如果是通过上一段描述的方式,那么则意味着你花钱购买的电视机中有一部分的功能纯属浪费钱,这也不合理。
装饰模式就能够很好地解决这样的实际问题,比如你需要给某个对象动态地增加一些功能(并且这种功能允许将来撤销),你又不想大动干戈地从上一级或更上级的父类下手,那么就请试试装饰模式吧。废话少说,看码说话:
1: using System;
2:
3: namespace Autumoon.DesignPatterns.Decorator
4: {
5: public abstract class Electronics
6: {
7: public abstract void Work();
8: }
9:
10: public class ConcreteElectronics : Electronics
11: {
12: private string _name { get; set; }
13:
14: public ConcreteElectronics(string name)
15: {
16: this._name = name;
17: }
18:
19: public override void Work()
20: {
21: Console.WriteLine("Electronics: " + this._name);
22: }
23: }
24:
25: public abstract class Decorator : Electronics
26: {
27: private Electronics _actualElectronics { get; set; }
28:
29: public void SetElectronics(Electronics electronics)
30: {
31: this._actualElectronics = electronics;
32: }
33:
34: public override void Work()
35: {
36: if (this._actualElectronics != null)
37: {
38: this._actualElectronics.Work();
39: }
40: }
41: }
42:
43: public class ConcreteDecorator : Decorator
44: {
45: private string _name { get; set; }
46:
47: public ConcreteDecorator(string name)
48: {
49: this._name = name;
50: }
51:
52: public override void Work()
53: {
54: CustomDecoration();
55: base.Work();
56: }
57:
58: public void CustomDecoration()
59: {
60: Console.WriteLine("Decorator: " + this._name);
61: }
62: }
63:
64: public class DecoratorClient
65: {
66: public Electronics Setup()
67: {
68: ConcreteElectronics tv = new ConcreteElectronics("Television.");
69:
70: ConcreteDecorator digitalVideoNetworks = new ConcreteDecorator("Digital Video Networks for Television");
71: digitalVideoNetworks.SetElectronics(tv);
72:
73: return digitalVideoNetworks;
74: }
75: }
76: }
当您看懂了上面代码所描述的情景,那么接下来您就可以装上机顶盒收看你喜欢的电视频道了:
1: static void Main(string[] args)
2: {
3: #region Decorator
4: //Electronics component = new DecoratorClient().Setup();
5: //component.Work();
6: #endregion
7:
8: Console.ReadLine();
9: }