第八课 装饰模式
装饰模式也是很常用的哦,我记得原来打印小票的时候用过他。其实就是写一个基类,定义一个基础方法,然后子类中在这个基础方法上进行扩充。大概就是这个样子了。
看下定义:
动态给一个对象添加一些额外的职责。
那么,为什么要使用装饰模式呢?一般来说,我们扩展一个类,都是通过继承的方式,这种实现方式无可厚非,但是如果要扩展的东西种类繁多,但是(注意)里面都能够找到一点共同点的话,那么这是后就可以考虑装饰模式了。
先看一个例子,这个例子是简化了原来我写得一个打印小票的例子出来的。
C#代码:
1. using System;
2. using System.Collections.Generic;
3. using System.Text;
4.
5. namespace 装饰模式
6. {
7. class Program
8. {
9. static void Main (string[] args)
10. {
11. ConcreteComponent c = new ConcreteComponent();
12. ConcreteDecoratorHead d1 = new ConcreteDecoratorHead();
13. ConcreteDecoratorTail d2 = new ConcreteDecoratorTail();
14.
15. d1.SetComponent(c);
16. d2.SetComponent(d1);
17.
18. d2.Print();
19.
20. Console.Read();
21. }
22. }
23.
24. abstract class Component
25. {
26. public abstract void Print();
27. }
28.
29. class ConcreteComponent : Component
30. {
31. public override void Print()
32. {
33. Console.WriteLine("打印票据的具体内容");
34. }
35. }
36.
37. abstract class Decorator : Component
38. {
39. protected Component component;
40.
41. public void SetComponent(Component component)
42. {
43. this.component = component;
44. }
45.
46. public override void Print()
47. {
48. if (component != null)
49. {
50. component.Print();
51. }
52. }
53. }
54.
55. class ConcreteDecoratorHead : Decorator
56. {
57. public override void Print()
58. {
59. Console.WriteLine("-----Head-----");
60. base.Print();
61.
62. }
63. }
64.
65. class ConcreteDecoratorTail : Decorator
66. {
67.
68. public override void Print()
69. {
70. base.Print();
71. Console.WriteLine("-----Tail-----");
72. }
73.
74.
75. }
76. }
77.
这个例子很简单,现在我要打印超市小票(类似),中间肯定是打印的主题内容。但是一般小票都有票头和票尾对吧,要能够方便的添加及修改。来分析代码
首先Component 定义了票据的打印方法 Print 。
然后ConcreteComponent 继承Component 并实现Print方法。(这里我用这个类来打印票据主体)
最后ConcreteDecoratorHead 与ConcreteDecoratorTail 分别实现了头部打印与尾部打印。通过重写 Print 方法,并调用父类方法的方式实现 。
再来看调用的方式。
78. ConcreteComponent c = new ConcreteComponent();
79. ConcreteDecoratorHead d1 = new ConcreteDecoratorHead();
80. ConcreteDecoratorTail d2 = new ConcreteDecoratorTail();
81.
82. d1.SetComponent(c);
83. d2.SetComponent(d1);
84.
85. d2.Print();
来看输出效果:
这样如果我想修改一下票头,或这修改下票尾都很方便。如果想不要票头也很容易。如果想要别的效果(例如双层票头)那么我再嵌套一层即可。
总之我的效果是通过给我打印票据内容这个基类上,进行装饰来实现的。这也就是装饰模式为什么这样命名的原因了。
其实用过java的同志看到调用的那几行代码是否有似曾相识的感觉?记得JavaIO流的处理方法吗?
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
是否很眼熟的代码?仔细分析下,其实这不就是装饰模式吗。定义了一个基类FileReader 里面有 read()方法不是。然后BufferedReader呢,无非给Read()方法进行了缓冲处理,就是装饰了一下下FileReader吗不是。
有兴趣的可以看看Java的实现方法。
本课结束。
作者:王文斌
转载请注明出处