小斑马

我的IT学习:计算机视觉、python

导航

访问者模式——Visitor

动机:

在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法(虚方法)),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计。

如何在不更改类层次结构的前提下,在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作,从而避免上述问题?

意图

表示一个作用于某对象结构中的各元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。

——《设计模式》GoF

Visitor模式的几个要点

• Visitor模式通过所谓双重分发(double dispatch)来实现在不更改Element类层次结构的前提下,在运行时透明地为类层次结构上的各个类动态添加新的操作。

• 所谓双重分发即Visitor模式中间包括了两个多态分发(注意其中的多态机制):第一个为accept方法的多态辨析;第二个为visit方法的多态辨析。

• Visitor模式的最大缺点在于扩展类层次结构(增添新的Element子类),会导致Visitor类的改变。因此Vistor模式适用于“Element类层次结构稳定,而其中的操作却经常面临频繁改动”。

Code
  1 // Visitor pattern -- Structural example
2
3 using System;
4 using System.Collections.Generic;
5
6 namespace DoFactory.GangOfFour.Visitor.Structural
7 {
8 /// <summary>
9 /// MainApp startup class for Structural
10 /// Visitor Design Pattern.
11 /// </summary>
12 class MainApp
13 {
14 static void Main()
15 {
16 // Setup structure
17 ObjectStructure o = new ObjectStructure();
18 o.Attach(new ConcreteElementA());
19 o.Attach(new ConcreteElementB());
20
21 // Create visitor objects
22 ConcreteVisitor1 v1 = new ConcreteVisitor1();
23 ConcreteVisitor2 v2 = new ConcreteVisitor2();
24
25 // Structure accepting visitors
26 o.Accept(v1);
27 o.Accept(v2);
28
29 // Wait for user
30 Console.ReadKey();
31 }
32 }
33
34 /// <summary>
35 /// The 'Visitor' abstract class
36 /// </summary>
37 abstract class Visitor
38 {
39 public abstract void VisitConcreteElementA(
40 ConcreteElementA concreteElementA);
41 public abstract void VisitConcreteElementB(
42 ConcreteElementB concreteElementB);
43 }
44
45 /// <summary>
46 /// A 'ConcreteVisitor' class
47 /// </summary>
48 class ConcreteVisitor1 : Visitor
49 {
50 public override void VisitConcreteElementA(
51 ConcreteElementA concreteElementA)
52 {
53 Console.WriteLine("{0} visited by {1}",
54 concreteElementA.GetType().Name, this.GetType().Name);
55 }
56
57 public override void VisitConcreteElementB(
58 ConcreteElementB concreteElementB)
59 {
60 Console.WriteLine("{0} visited by {1}",
61 concreteElementB.GetType().Name, this.GetType().Name);
62 }
63 }
64
65 /// <summary>
66 /// A 'ConcreteVisitor' class
67 /// </summary>
68 class ConcreteVisitor2 : Visitor
69 {
70 public override void VisitConcreteElementA(
71 ConcreteElementA concreteElementA)
72 {
73 Console.WriteLine("{0} visited by {1}",
74 concreteElementA.GetType().Name, this.GetType().Name);
75 }
76
77 public override void VisitConcreteElementB(
78 ConcreteElementB concreteElementB)
79 {
80 Console.WriteLine("{0} visited by {1}",
81 concreteElementB.GetType().Name, this.GetType().Name);
82 }
83 }
84
85 /// <summary>
86 /// The 'Element' abstract class
87 /// </summary>
88 abstract class Element
89 {
90 public abstract void Accept(Visitor visitor);
91 }
92
93 /// <summary>
94 /// A 'ConcreteElement' class
95 /// </summary>
96 class ConcreteElementA : Element
97 {
98 public override void Accept(Visitor visitor)
99 {
100 visitor.VisitConcreteElementA(this);
101 }
102
103 public void OperationA()
104 {
105 }
106 }
107
108 /// <summary>
109 /// A 'ConcreteElement' class
110 /// </summary>
111 class ConcreteElementB : Element
112 {
113 public override void Accept(Visitor visitor)
114 {
115 visitor.VisitConcreteElementB(this);
116 }
117
118 public void OperationB()
119 {
120 }
121 }
122
123 /// <summary>
124 /// The 'ObjectStructure' class
125 /// </summary>
126 class ObjectStructure
127 {
128 private List<Element> _elements = new List<Element>();
129
130 public void Attach(Element element)
131 {
132 _elements.Add(element);
133 }
134
135 public void Detach(Element element)
136 {
137 _elements.Remove(element);
138 }
139
140 public void Accept(Visitor visitor)
141 {
142 foreach (Element element in _elements)
143 {
144 element.Accept(visitor);
145 }
146 }
147 }
148 }

  

说明:文字摘自webcast讲座,代码图片摘自dofactory

posted on 2011-08-19 22:00  小斑马  阅读(175)  评论(0编辑  收藏  举报