一、通路者模式定義
1.通路者模式是一種将資料結構與資料操作分離的設計模式,是指封裝一些作用于某種資料結構中的各元素的操作,它可以在不改變資料結構的前提下定義作用于這些元素的新的操作。屬于行為型模式。
2.通路者模式被稱為最複雜的設計模式,并且使用頻率不高,設計模式的作者也評價為:大多情況下,你不需要使用通路者模式,但是一旦需要使用它時,那就真的需要使用了。通路者模式的基本思想是,針對系統中擁有固定類型數的對象結構(元素),在其内提供一個accept()方法用來接受通路者對象的通路。不同的通路者對同一進制素的通路内容不同,使得相同的元素集合可以産生不同的資料結果。accept()方法可以接收不同的通路者對象,然後在内部将自己(元素)轉發到接收到的通路者對象的visit()方法内。通路者内部對應類型的visit()方法就會得到回調執行,對元素進行操作。也即是通過兩次動态分發(第一次是對通路者的分發accept()方法,第二次是對元素的分發visit()方法),才最終将一個具體的元素傳遞到一個具體的通路者。如此一來,就解耦了資料結構與操作,且資料操作不會改變元素狀态
3.通路者模式的核心是解耦資料結構與資料操作,使得對元素的操作具備優秀的擴充性。可以通過擴充不同的資料操作類型(通路者)實作對相同元素集的不同的操作
4.通路者模式的适用場景:
A.資料結構穩定,作用于資料結構的操作經常變化的場景
B.需要資料結構與資料操作分離的場景
C.需要對不同資料類型(元素)進行操作,而不使用分支判斷具體類型的場景
二、通路者模式示例
1.通路者模式一般包含5種角色:
A.抽象通路者(Visitor):接口或抽象類
B.具體通路者(ConcreteVisitor):實作對具體元素的操作
C.抽象元素(Element):接口或抽象類,定義了一個接受通路者通路的方法accept(),表示所有元素類型都支援被通路者通路
D.具體元素(ConcreteElement):具體元素類型,提供接受通路者的具體實作,通常的實作都為:visitor.visit(this)
E.結構對象(ObjectStructure):該類内部維護了元素集合,并提供方法接受通路者對該集合所有元素進行操作
2.代碼示例
1 // 抽象通路者
2 public interface IVisitor {
3
4 void visit(ConcreteElementA element);
5
6 void visit(ConcreteElementB element);
7 }
8
9 // 具體通路者
10 public class ConcreteVisitorA implements IVisitor {
11
12 public void visit(ConcreteElementA element) {
13 String result = element.operationA();
14 System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
15 }
16
17 public void visit(ConcreteElementB element) {
18 int result = element.operationB();
19 System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
20 }
21 }
22
23 // 具體通路者
24 public class ConcreteVisitorB implements IVisitor {
25
26 public void visit(ConcreteElementA element) {
27 String result = element.operationA();
28 System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
29 }
30
31
32 public void visit(ConcreteElementB element) {
33 int result = element.operationB();
34 System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
35 }
36 }
37
38 // 抽象元素
39 public interface IElement {
40 void accept(IVisitor visitor);
41 }
42
43 // 具體元素
44 public class ConcreteElementA implements IElement {
45
46 public void accept(IVisitor visitor) {
47 visitor.visit(this);
48 }
49
50 public String operationA() {
51 return this.getClass().getSimpleName();
52 }
53
54 }
55
56 // 具體元素
57 public class ConcreteElementB implements IElement {
58
59 public void accept(IVisitor visitor) {
60 visitor.visit(this);
61 }
62
63 public int operationB() {
64 return new Random().nextInt(100);
65 }
66 }
67
68 // 結構對象
69 public class ObjectStructure {
70 private List<IElement> list = new ArrayList<IElement>();
71
72 {
73 this.list.add(new ConcreteElementA());
74 this.list.add(new ConcreteElementB());
75 }
76
77 public void accept(IVisitor visitor) {
78 for (IElement element : this.list) {
79 element.accept(visitor);
80 }
81 }
82 }
83
84 public class Test {
85
86 public static void main(String[] args) {
87 ObjectStructure collection = new ObjectStructure();
88 System.out.println("ConcreteVisitorA handle elements:");
89 IVisitor visitorA = new ConcreteVisitorA();
90 collection.accept(visitorA);
91 System.out.println("------------------------------------");
92 System.out.println("ConcreteVisitorB handle elements:");
93 IVisitor visitorB = new ConcreteVisitorB();
94 collection.accept(visitorB);
95 }
96
97 }
3.通路者模式的優缺點
A.優點
a.解耦了資料結構和資料操作,使得操作集合可以獨立變化
b.擴充性好:可以通過擴充通路者角色,實作對資料集的不同操作
c.元素具體類型并非單一,通路者均可操作
d.各角色職責分離,符合單一職責原則
B.缺點