訪問者模式
目的是封裝一些施加於某種數據結構元素之上的操做。一旦這些操做須要修改的話,接受這個操做的數據結構則能夠保持不變。
問題提出
System.Collection命名空間下提供了大量集合操做對象。但大多數狀況下處理的都是同類對象的彙集。換言之,在彙集上採起的操做都是一些針對同類型對象的同類操做。可是若是針對一個保存有不一樣類型對象的彙集採起某種操做該怎麼辦呢?
粗看上去,這彷佛不是什麼難題。但是若是須要針對一個包含不一樣類型元素的彙集採起某種操做,而操做的細節根據元素的類型不一樣而有所不一樣時,就會出現必須對元素類型作類型判斷的條件轉移語句。這個時候,使用訪問者模式就是一個值得考慮的解決方案。
訪問者模式
訪問者模式適用於數據結構相對未定的系統,它把數據結構和做用於結構上的操做之間的耦合解脫開,使得操做集合能夠相對自由地演化。
數據結構的每個節點均可以接受一個訪問者的調用,此節點向訪問者對象傳入節點對象,而訪問者對象則反過來執行節點對象的操做。這樣的過程叫作"雙重分派"。節點調用訪問者,將它本身傳入,訪問者則將某算法針對此節點執行。
雙重分派意味着施加於節點之上的操做是基於訪問者和節點自己的數據類型,而不單單是其中的一者。
java
定義:封裝某些做用於某種數據結構中各元素的操做,它能夠在不改變數據結構的前提下定義做用於這些元素的新的操做。算法
類型:行爲類模式數據結構
類圖:dom
元素Element:ide
package visitor; public interface Elements { public void accept(Visitor visitor); public void domethod(); }
元素的具體類 AdminElement:測試
package visitor; public class AdminElement implements Elements{ @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visit(this); } @Override public void domethod() { // TODO Auto-generated method stub System.out.println("visiting adminElement"); } }
元素具體類 customerElement:this
package visitor; public class CustomerElement implements Elements{ @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visit(this); } @Override public void domethod() { // TODO Auto-generated method stub System.out.println("visit customer function"); } }
訪問者接口Visitor:spa
package visitor; public interface Visitor { public void visit(AdminElement adminElement ); public void visit(CustomerElement customerElement); }
訪問者實現類AdminVisitor:code
package visitor; public class AdminVisitor implements Visitor{ @Override public void visit(AdminElement adminElement) { // TODO Auto-generated method stub adminElement.domethod(); } @Override public void visit(CustomerElement customerElement) { // TODO Auto-generated method stub System.out.println("admin cannot visit customer"); } }
訪問者實現類customer:對象
package visitor; public class CustomerVisitor implements Visitor{ @Override public void visit(AdminElement adminElement) { // TODO Auto-generated method stub System.out.println("no permission ~!"); } @Override public void visit(CustomerElement customerElement) { // TODO Auto-generated method stub customerElement.domethod(); } }
客戶端代碼:
package visitor; import java.util.ArrayList; import java.util.List; public class MainFunction { public static void main(String[] args) { // TODO Auto-generated method stub List<Elements> list = new ArrayList<Elements>(); for(int i=0;i<10;i++) list.add(Creator.newElement()); AdminVisitor av = new AdminVisitor(); CustomerVisitor cv = new CustomerVisitor(); // adminVistor訪問 for (Elements elements : list) { elements.accept(av); } System.out.println("-------------------------"); //customerVistor訪問 for (Elements elements : list) { elements.accept(cv); } } }
建立測試對象類creator:
package visitor; import java.util.Random; public class Creator { public static Elements newElement() { Random r = new Random(); switch (r.nextInt(2)) { case 0: return new AdminElement(); case 1: return new CustomerElement(); default: return new AdminElement(); } } }