1.访问者模式:模式的优点在于保护了被访元素的信息完整性,user只需要通过第三方(objectstructre结构体)就可以完成一个访问过程。而且,被访问的元素可以随时从结构体内增加或删除,也体现了访问者模式的易扩展性。
2. 访问者模式据说是设计模式里面最难懂的,但我觉得最难的还是动态代理模式。那么接下来说一下访问者模式的"难懂"在哪儿? 为了保护"被访问者"的信息,访问者模式将 "访问者" 与 "被访问者" 之间用一个objectstructre类隔开,user只需把访问者通过结构体的accept()函数就可以访问到objectstructre结构体里面的全部被访元素,而visitor和element之间的来回调用函数,就是访问者模式里面最难懂的。
Visitor:访问者抽象类
ConcretVisitor:访问者具体类
Element:被访者抽象类
ConcreteElement:被访者具体类
ObjectStruture:存储被访者 和 接收访问者的类
3.例子:假设 周杰伦 和 梅西 要去买房子,那么他们将去参观三间房子houseA,houseB和houseC. 接下来看代码实现。
访问者的抽象类,声明3个重载的方法,分别接收houseA,B,C三个对象,getVisitorName()函数返回访问者名字
package pers.reus.model.visitor.impl;
import pers.reus.model.element.HouseA;
import pers.reus.model.element.HouseB;
import pers.reus.model.element.HouseC;
//访问者的抽象类
public abstract class Visitor {
//分别访问A,B,C
public abstract void visit(HouseA h);
public abstract void visit(HouseB h);
public abstract void visit(HouseC h);
//获得自身(访问者)的名字
public abstract String getVisitorName();
}
被访问元素的抽象类,2个函数,分别是接收访问者的函数是展示自身信息的函数
package pers.reus.model.element.impl;
import pers.reus.model.visitor.impl.Visitor;
//被访问者的抽象类
public abstract class Element {
//accept()接受访问者
public abstract void accept(Visitor v);
//showMySelf()展示自身信息
public abstract void showMySelf(Visitor v);
}
被访问元素的具体实现,当调用accept时,函数内会调用访问者类的visit函数,而visit函数又会再调用houseA类的showMySelf函数,这就是访问者模式里面最难懂的部分,因为这个部分最终目的是调用showMySelf(),但是却经过2次来回的调用。
package pers.reus.model.element;
import pers.reus.model.element.impl.Element;
import pers.reus.model.visitor.impl.Visitor;
public class HouseA extends Element{
//展示自身信息
public void showMySelf(Visitor v) {
// TODO Auto-generated method stub
System.out.println(v.getVisitorName() + " 参观了 " + " HouseA");
}
//接受访问者,并调用访问者里面的visit()函数来访问自身
public void accept(Visitor v) {
// TODO Auto-generated method stub
v.visit(this);
}
}
houseB和houseA的代码完全一样。
package pers.reus.model.element;
import pers.reus.model.element.impl.Element;
import pers.reus.model.visitor.impl.Visitor;
public class HouseB extends Element{
//展示自身信息
public void showMySelf(Visitor v) {
// TODO Auto-generated method stub
System.out.println(v.getVisitorName() + " 参观了 " + " HouseB");
}
//接受访问者,并调用访问者里面的visit()函数来访问自身
public void accept(Visitor v) {
// TODO Auto-generated method stub
v.visit(this);
}
}
访问者的具体实现类,继承父类三个具体方法,这样可以针对性去访问三个被访元素,注:如果被visit()函数里面的houseA,houseB等换成Element是不能运行的,必须换成具体的实现类
package pers.reus.model.visitor;
import pers.reus.model.element.HouseA;
import pers.reus.model.element.HouseB;
import pers.reus.model.element.HouseC;
import pers.reus.model.visitor.impl.Visitor;
public class JayChou extends Visitor{
//面对不同的被访问者,有他们的特定函数去访问那他们
public void visit(HouseA h) {
// TODO Auto-generated method stub
h.showMySelf(this);
}
public void visit(HouseB h) {
// TODO Auto-generated method stub
h.showMySelf(this);
}
public void visit(HouseC h) {
// TODO Auto-generated method stub
h.showMySelf(this);
}
//返回自身名字
public String getVisitorName(){
return "JayChou";
}
}
结构体ObjectStructure,他在作用就是1.接收被访元素和删除被访元素 2.帮助访问者去 访问 被访元素。accept()函数里面调用了element里面的accpet(),只要调试一次就懂了
package pers.reus.model.Structure;
import java.util.ArrayList;
import java.util.List;
import pers.reus.model.element.impl.Element;
import pers.reus.model.visitor.impl.Visitor;
//存储被访问的element的结构体ObjectStructure
public class ObjectStructure
{
//用List存下对象Element
private final List<Element> elements = new ArrayList<Element>();
//增加Element的函数
public void addElement(final Element e)
{
elements.add(e);
}
//删除Element的函数
public void removeElement(final Element e)
{
elements.remove(e);
}
//接受访问者,并带领访问者去访问所有存在List里面的Element
public void accept(final Visitor visitor)
{
for (final Element e : elements)
{
e.accept(visitor);
}
}
}
最后就是client类的测试,1.声明结构体 2.声明被访元素 3.被访元素放入结构体内 4.声明访问者 5.结构体接收访问者,"带" 访问者去访问所有存储在结构体内的被访元素
package pers.reus.model.client;
import pers.reus.model.Structure.ObjectStructure;
import pers.reus.model.element.HouseA;
import pers.reus.model.element.HouseB;
import pers.reus.model.element.HouseC;
import pers.reus.model.element.impl.Element;
import pers.reus.model.visitor.JayChou;
import pers.reus.model.visitor.Messi;
import pers.reus.model.visitor.impl.Visitor;
public class VisitorPatternClient {
public static void main(String[] args) {
//声明存储被访问的element的结构体
ObjectStructure o = new ObjectStructure();
//声明3个被访问者()
Element houseA = new HouseA();
Element houseB = new HouseB();
Element houseC = new HouseC();
//把被访问者加入结构体中
o.addElement(houseA);
o.addElement(houseB);
o.addElement(houseC);
//声明2个访问者,周杰伦和梅西
Visitor JayChou = new JayChou();
Visitor Messi = new Messi();
//通过结构体让访问者访问所有element
o.accept(JayChou);
o.accept(Messi);
}
}