【Java设计模式】· 访问者模式(Visitor Pattern)

来源:互联网 发布:六轴机械手臂 算法 编辑:程序博客网 时间:2024/05/29 10:12

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,Cpublic 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 stubSystem.out.println(v.getVisitorName() + " 参观了 " + " HouseA");}//接受访问者,并调用访问者里面的visit()函数来访问自身public void accept(Visitor v) {// TODO Auto-generated method stubv.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 stubSystem.out.println(v.getVisitorName() + " 参观了 " + " HouseB");}//接受访问者,并调用访问者里面的visit()函数来访问自身public void accept(Visitor v) {// TODO Auto-generated method stubv.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 stubh.showMySelf(this);}public void visit(HouseB h) {// TODO Auto-generated method stubh.showMySelf(this);}public void visit(HouseC h) {// TODO Auto-generated method stubh.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的结构体ObjectStructurepublic 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();//通过结构体让访问者访问所有elemento.accept(JayChou);o.accept(Messi);}}



0 0
原创粉丝点击