表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作,它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作
這里寫圖片描述
訪問(wèn)者模式的優(yōu)點(diǎn)
1、符合單一職責(zé)原則:凡是適用訪問(wèn)者模式的場(chǎng)景中,元素類中需要封裝在訪問(wèn)者中的操作必定是與元素類本身關(guān)系不大且是易變的操作,使用訪問(wèn)者模式一方面符合單一職責(zé)原則,另一方面,因?yàn)楸环庋b的操作通常來(lái)說(shuō)都是易變的,所以當(dāng)發(fā)生變化時(shí),就可以在不改變?cè)仡惐旧淼那疤嵯拢瑢?shí)現(xiàn)對(duì)變化部分的擴(kuò)展。
2、擴(kuò)展性良好:元素類可以通過(guò)接受不同的訪問(wèn)者來(lái)實(shí)現(xiàn)對(duì)不同操作的擴(kuò)展。
訪問(wèn)者模式的適用場(chǎng)景
假如一個(gè)對(duì)象中存在著一些與本對(duì)象不相干(或者關(guān)系較弱)的操作,為了避免這些操作污染這個(gè)對(duì)象,則可以使用訪問(wèn)者模式來(lái)把這些操作封裝到訪問(wèn)者中去。
假如一組對(duì)象中,存在著相似的操作,為了避免出現(xiàn)大量重復(fù)的代碼,也可以將這些重復(fù)的操作封裝到訪問(wèn)者中去。
但是,訪問(wèn)者模式并不是那么完美,它也有著致命的缺陷: ***增加新的元素類比較困難*** 。通過(guò)訪問(wèn)者模式的代碼可以看到,在訪問(wèn)者類中,每一個(gè)元素類都有它對(duì)應(yīng)的處理方法,也就是說(shuō),每增加一個(gè)元素類都需要修改訪問(wèn)者類(也包括訪問(wèn)者類的子類或者實(shí)現(xiàn)類),修改起來(lái)相當(dāng)麻煩。也就是說(shuō),在元素類數(shù)目不確定的情況下,應(yīng)該慎用訪問(wèn)者模式。所以,訪問(wèn)者模式比較適用于對(duì)已有功能的重構(gòu),比如說(shuō),一個(gè)項(xiàng)目的基本功能已經(jīng)確定下來(lái),元素類的數(shù)據(jù)已經(jīng)基本確定下來(lái)不會(huì)變了,會(huì)變的只是這些元素內(nèi)的相關(guān)操作,這時(shí)候,我們可以使用訪問(wèn)者模式對(duì)原有的代碼進(jìn)行重構(gòu)一遍,這樣一來(lái),就可以在不修改各個(gè)元素類的情況下,對(duì)原有功能進(jìn)行修改。
代碼
Main
public class Main {
public static void main(String[] args) {
ObjectStructure os=new ObjectStructure();
os.add(new ConcreteElementA());
os.add(new ConcreteElementB());
os.action(new ConcreteVistor());
}
}
ObjectStructure
public class ObjectStructure{
private List<Element> el=new ArrayList<Element>();
public boolean add(Element e){
try{
el.add(e);
}catch(Exception e1){
System.out.println(e1);
return false;
}
return true;
}
public void action(myInterface.Vistor v){
for(int i=0;i<el.size();i++){
el.get(i).accpet(v);
}
}
}
interface:Vistor
public interface Vistor {
public void visitConcreteElement(Element e);
}
interface:Element
public interface Element {
public void accpet(Vistor v);
public void doSomething();
}
imp:ConcreteVistor
public class ConcreteVistor implements Vistor {
@Override
public void visitConcreteElement(Element e) {
e.doSomething();
}
}
imp:ConcreteElementA
public class ConcreteElementA implements Element {
@Override
public void accpet(Vistor v) {
v.visitConcreteElement(this);
}
@Override
public void doSomething() {
System.out.println("this is A");
}
}
imp:ConcreteElementB
public class ConcreteElementB implements Element {
@Override
public void accpet(Vistor v) {
v.visitConcreteElement(this);
}
@Override
public void doSomething() {
System.out.println("this is B");
}
}