1. 聯合組合模式
//抽象的組件對象,相當于訪問者模式中的元素對象
public abstract class Component {//接受訪問者的訪問 public abstract void
accept(Visitor visitor
);//向組合對象中加入組件對象 public void addChild(Component child) {// 缺省的實現,拋出例外,因為葉子對象沒有這個功能,或者子組件沒有實現這個功能throw new
UnsupportedOperationException("對象不支持這個功能"); }//從組合對象中移出某個組件對象 public void removeChild(Component child) {// 缺省的實現,拋出例外,因為葉子對象沒有這個功能,或者子組件沒有實現這個功能throw new
UnsupportedOperationException("對象不支持這個功能"); }// 返回某個索引對應的組件對象 public Component getChildren(int index) {throw new
UnsupportedOperationException("對象不支持這個功能");}
}public class Leaf extends Component{public void accept(Visitor visitor) {//回調訪問者對象的相應方法visitor.
visitLeaf(this
);}private String name =
""; //葉子對象的名字 public Leaf(String name){this.name = name
;}public String getName() {return name
;}
}//循環子元素,讓子元素也接受訪問
public class Composite extends Component{public void accept(Visitor visitor) {//回調訪問者對象的相應方法visitor.
visitComposite(this
);//循環子元素,讓子元素也接受訪問for(Component c : childComponents){//調用子對象接受訪問,變相實現遞歸c.
accept(visitor
);}}//用來存儲組合對象中包含的子組件對象 private List<Component> childComponents = new ArrayList<Component>
(); private String name =
"";//組合對象的名字 public Composite(String name){this.name = name
;} public void addChild(Component child) {childComponents.
add(child
);}public String getName() {return name
;}
}public interface Visitor {//訪問組合對象,相當于給組合對象添加訪問者的功能 public void
visitComposite(Composite composite
);//訪問葉子對象,相當于給葉子對象添加訪問者的功能 public void
visitLeaf(Leaf leaf
);
}public class PrintNameVisitor implements Visitor {public void visitComposite(Composite composite) {//訪問到組合對象的數據System.out.
println("節點:"+composite.
getName());}public void visitLeaf(Leaf leaf) {//訪問到葉子對象的數據 System.out.
println("葉子:"+leaf.
getName());}
}public class ObjectStructure {//表示對象結構,可以是一個組合結構 private Component root = null
;public void handleRequest(Visitor visitor){//讓組合對象結構中的根元素,接受訪問//在組合對象結構中已經實現了元素的遍歷if(root!=null){root.
accept(visitor
);}}// 傳入組合對象結構 public void setRoot(Component ele){this.root = ele
;}
}public static void main(String[] args) {//定義所有的組合對象Component root = new
Composite("服裝");Component c1 = new
Composite("男裝");Component c2 = new
Composite("女裝");//定義所有的葉子對象Component leaf1 = new
Leaf("襯衣");Component leaf2 = new
Leaf("夾克");Component leaf3 = new
Leaf("裙子");Component leaf4 = new
Leaf("套裝");//按照樹的結構來組合組合對象和葉子對象root.
addChild(c1
);root.
addChild(c2
);c1.
addChild(leaf1
);c1.
addChild(leaf2
);c2.
addChild(leaf3
);c2.
addChild(leaf4
);//創建ObjectStructureObjectStructure os = new
ObjectStructure();os.
setRoot(root
);//調用ObjectStructure來處理請求功能Visitor psVisitor = new
PrintNameVisitor();
// root.
accept(psVisitor
); os.
handleRequest(psVisitor
);//或者去掉ObjectStructure //調用根元素的方法來接受請求功能Visitor psVisitor = new
PrintStructVisitor(); root.
accept(psVisitor
);
}
1.1.有的時候可以省略ObjectStructure ,client直接調用
1.2. 改造版
假設要輸出下面的結果:定制“+”、“-”
public class PrintStructVisitor implements Visitor { private String preStr =
"";//用來累計記錄對象需要向后退的格public void visitComposite(Composite composite) {//先把自己輸出去System.out.
println(preStr+
"+"+composite.
getName());//如果還包含有子組件,那么就輸出這些子組件對象if(composite.getChildComponents()!=null){//然后添加一個空格,表示向后縮進一個空格preStr+=
" "; //輸出當前對象的子對象了for(Component c : composite.getChildComponents()){//遞歸輸出每個子對象c.
accept(this
);}//把循環子對象所多加入的一個退格給去掉preStr = preStr.
substring(0,preStr.
length()-1
);}}public void visitLeaf(Leaf leaf) {//訪問到葉子對象的數據 System.out.
println(preStr+
"-"+leaf.
getName());}
}
2. 總結
2.1 訪問者模式有以下缺點
對象結構變化很困難
不適用于對象結構中的類經常變化的情況,因為對象結構發生了改變,訪問者的接口和訪問者的實現都要發生相應的改變,代價太高。
破壞封裝
訪問者模式通常需要對象結構開放內部數據給訪問者和ObjectStructrue,這破壞了對象的封裝性。
2.2 訪問者模式的本質:預留通路,回調實現。
仔細思考訪問者模式,它的實現主要是通過預先定義好調用的通路,在被訪問的對象上定義accept方法,在訪問者的對象上定義visit方法;然后在調用真正發生的時候,通過兩次分發技術,利用預先定義好的通路,回調到訪問者具體的實現上。
明白了訪問者模式的本質,就可以在定義一些通用功能,或者設計工具類的時候讓訪問者模式派上大用場。你可以把已經實現好的一些功能作為已有的對象結構,因為在今后可能會根據實際需要為它們增加新的功能,甚至希望開放接口來讓其他開發人員擴展這些功能,所以你可以用訪問者模式來設計,在這個對象結構上預留好通用的調用通路,在以后添加功能,或者是其他開發人員來擴展的時候,只需要提供新的訪問者實現,就能夠很好地加入到系統中來了。
2.3 建議在以下情況中選用訪問者模式。
如果想對一個對象結構實施一些依賴于對象結構中具體類的操作,可以使用訪問者模式。
如果想對一個對象結構中的各個元素進行很多不同的而且不相關的操作,為了避免這些操作使類變得雜亂,可以使用訪問者模式。把這些操作分散到不同的訪問者對象中去,每個訪問者對象實現同一類功能。
如果對象結構很少變動,但是需要經常給對象結構中的元素對象定義新的操作,可以使用訪問者模式。
總結
以上是生活随笔為你收集整理的《研磨设计模式》chap25 访问者模式Visitor(3)联合组合模式+总结的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。