前几天跟Yuan Ye Pair的时候发现了这个方法
1. 经典的Visitor模式(循环依赖)
classic visitor pattern
1 public interface Document
2 {
3 void Accept(DocumentVisitor visitor);
4 }
5
6 public class WordDocument : Document
7 {
8 public void Accept(DocumentVisitor visitor)
9 {
10 visitor.Visit(this);
11 }
12 }
13
14 public class ExcelDocument : Document
15 {
16 public void Accept(DocumentVisitor visitor)
17 {
18 visitor.Visit(this);
19 }
20 }
21
22 public interface DocumentVisitor
23 {
24 void Visit(WordDocument wordDocument);
25 void Visit(ExcelDocument excelDocument);
26 }
27
2 {
3 void Accept(DocumentVisitor visitor);
4 }
5
6 public class WordDocument : Document
7 {
8 public void Accept(DocumentVisitor visitor)
9 {
10 visitor.Visit(this);
11 }
12 }
13
14 public class ExcelDocument : Document
15 {
16 public void Accept(DocumentVisitor visitor)
17 {
18 visitor.Visit(this);
19 }
20 }
21
22 public interface DocumentVisitor
23 {
24 void Visit(WordDocument wordDocument);
25 void Visit(ExcelDocument excelDocument);
26 }
27
这里面 Document依赖于DocumentVisitor, DocumentVisitor依赖于WordDocument和ExcelDocument, 而WrodDocument等又依赖于Document
这样 Document->DocumentVisitor->WordDocument->Document->...循环依赖
2. 经典的解依赖Visitor模式(Down Cast)
decouple visitor (dynamic cast))
1 public interface Document
2 {
3 void Accept(DocumentVisitor visitor);
4 }
5
6 public class WordDocument : Document
7 {
8 public void Accept(DocumentVisitor visitor)
9 {
10 if (visitor is WordDocumentVisitor)
11 {
12 ((WordDocumentVisitor)visitor).Visit(this);
13 }
14 }
15 }
16
17 public class ExcelDocument : Document
18 {
19 public void Accept(DocumentVisitor visitor)
20 {
21 if (visitor is ExcelDocumentVisitor)
22 {
23 ((ExcelDocumentVisitor)visitor).Visit(this);
24 }
25 }
26 }
27
28 public interface DocumentVisitor
29 {
30 //空接口, 依赖在这里断掉了
31 }
32
33 public class ExcelDocumentVisitor : DocumentVisitor
34 {
35 public void Visit(ExcelDocument excelDocument)
36 {
37
38 }
39 }
40
41 public class WordDocumentVisitor : DocumentVisitor
42 {
43 public void Visit(WordDocument wordDocument)
44 {
45 }
46 }
47
2 {
3 void Accept(DocumentVisitor visitor);
4 }
5
6 public class WordDocument : Document
7 {
8 public void Accept(DocumentVisitor visitor)
9 {
10 if (visitor is WordDocumentVisitor)
11 {
12 ((WordDocumentVisitor)visitor).Visit(this);
13 }
14 }
15 }
16
17 public class ExcelDocument : Document
18 {
19 public void Accept(DocumentVisitor visitor)
20 {
21 if (visitor is ExcelDocumentVisitor)
22 {
23 ((ExcelDocumentVisitor)visitor).Visit(this);
24 }
25 }
26 }
27
28 public interface DocumentVisitor
29 {
30 //空接口, 依赖在这里断掉了
31 }
32
33 public class ExcelDocumentVisitor : DocumentVisitor
34 {
35 public void Visit(ExcelDocument excelDocument)
36 {
37
38 }
39 }
40
41 public class WordDocumentVisitor : DocumentVisitor
42 {
43 public void Visit(WordDocument wordDocument)
44 {
45 }
46 }
47
3. 消除无聊Accept()方法的Visitor模式
上面的Accept方法几乎千篇一律, 遵循相同的模式. 里面无非就是类型计算, 可以利用C#的泛型支持将之消除
remove Accept from all subclasses
1 public interface Document
2 {
3 void Accept(DocumentVisitor visitor);
4 }
5
6 public abstract class VisitableDocument<T> : Document where T : VisitableDocument<T>
7 {
8 public void Accept(DocumentVisitor visitor)
9 {
10 var interfaces = visitor.GetType().GetInterfaces();
11
12 foreach (var type in interfaces)
13 {
14 if (type.GetGenericArguments().Contains(typeof(T)))
15 {
16 ((DocumentVisitor<T>)visitor).Visit((T)this);
17 }
18 }
19 }
20 }
21
22 public class WordDocument : VisitableDocument<WordDocument>
23 {
24 //不需要自己实现Accept, 基类已经实现
25 }
26
27 public class ExcelDocument : VisitableDocument<ExcelDocument>
28 {
29 //不需要自己实现Accept, 基类已经实现
30 }
31
32 public interface DocumentVisitor
33 {
34 //空接口
35 }
36
37 public interface DocumentVisitor<T> : DocumentVisitor where T : VisitableDocument<T>
38 {
39 //泛型, 依赖在这里断掉了
40 void Visit(T document);
41 }
42
43 public class PrintDocumentVisitor : DocumentVisitor<WordDocument>, DocumentVisitor<ExcelDocument>
44 {
45 public void Visit(WordDocument wordDocument)
46 {
47 }
48
49 public void Visit(ExcelDocument excelDocument)
50 {
51 }
52 }
53
2 {
3 void Accept(DocumentVisitor visitor);
4 }
5
6 public abstract class VisitableDocument<T> : Document where T : VisitableDocument<T>
7 {
8 public void Accept(DocumentVisitor visitor)
9 {
10 var interfaces = visitor.GetType().GetInterfaces();
11
12 foreach (var type in interfaces)
13 {
14 if (type.GetGenericArguments().Contains(typeof(T)))
15 {
16 ((DocumentVisitor<T>)visitor).Visit((T)this);
17 }
18 }
19 }
20 }
21
22 public class WordDocument : VisitableDocument<WordDocument>
23 {
24 //不需要自己实现Accept, 基类已经实现
25 }
26
27 public class ExcelDocument : VisitableDocument<ExcelDocument>
28 {
29 //不需要自己实现Accept, 基类已经实现
30 }
31
32 public interface DocumentVisitor
33 {
34 //空接口
35 }
36
37 public interface DocumentVisitor<T> : DocumentVisitor where T : VisitableDocument<T>
38 {
39 //泛型, 依赖在这里断掉了
40 void Visit(T document);
41 }
42
43 public class PrintDocumentVisitor : DocumentVisitor<WordDocument>, DocumentVisitor<ExcelDocument>
44 {
45 public void Visit(WordDocument wordDocument)
46 {
47 }
48
49 public void Visit(ExcelDocument excelDocument)
50 {
51 }
52 }
53