天天看點

24通路者模式

一、通路者模式定義

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.缺點

繼續閱讀