设计模式-访问者模式

来源:互联网 发布:查看手机ip和端口 编辑:程序博客网 时间:2024/06/06 03:07

设计模式-访问者模式

1、概念

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

2、优点

1、符合单一职责原则。 
2、优秀的扩展性。 
3、灵活性。

3、缺点

1、具体元素对访问者公布细节,违反了迪米特原则。 
2、具体元素变更比较困难。 
3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

4、角色

1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。 
2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口。 
3.Element 定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。 
4.ConcreteElement 具体元素,实现了抽象元素(Element)所定义的接受操作接口。
 5.ObjectStructure 结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。

5、使用场景

1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 
2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

7、UML类图


8、代码解析UML类图

/** * Created by laizhiyuan on 2017/8/1. * * <p> *     设计模式-访问者模式-抽象访问者 * </p> */public abstract class Visitor {    public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);    public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);}

/** * Created by laizhiyuan on 2017/8/1. * * <p> *     设计模式-访问者模式-具体访问者A * </p> */public class ConcreteVisitorA extends Visitor {    /**     * 访问元素A时,做出的反应     * @param concreteElementA     */    @Override    public void visitConcreteElementA(ConcreteElementA concreteElementA) {        System.out.println(String.format("[%s][%s]访问", concreteElementA.getClass().getSimpleName(), ConcreteVisitorA.class.getSimpleName()));    }    /**     * 访问元素B时,做出的反应     * @param concreteElementB     */    @Override    public void visitConcreteElementB(ConcreteElementB concreteElementB) {        System.out.println(String.format("[%s][%s]访问", concreteElementB.getClass().getSimpleName(), ConcreteVisitorA.class.getSimpleName()));    }}

/** * Created by laizhiyuan on 2017/8/1. * * <p> *     设计模式-访问者模式-具体访问者B * </p> */public class ConcreteVisitorB extends Visitor {    /**     * 访问元素A时,做出的反应     * @param concreteElementA     */    @Override    public void visitConcreteElementA(ConcreteElementA concreteElementA) {        System.out.println(String.format("[%s][%s]访问", concreteElementA.getClass().getSimpleName(), ConcreteVisitorB.class.getSimpleName()));    }    /**     * 访问元素B时,做出的反应     * @param concreteElementB     */    @Override    public void visitConcreteElementB(ConcreteElementB concreteElementB) {        System.out.println(String.format("[%s][%s]访问", concreteElementB.getClass().getSimpleName(), ConcreteVisitorB.class.getSimpleName()));    }}

/** * Created by laizhiyuan on 2017/8/1. * * * <p> *     设计模式-访问者模式-抽象元素 * </p> */public abstract class Element {    public abstract void accept(Visitor visitor);}

/** * Created by laizhiyuan on 2017/8/1. * * * <p> *     设计模式-访问者模式-具体元素A * </p> */public class ConcreteElementA extends Element {    @Override    public void accept(Visitor visitor) {        visitor.visitConcreteElementA(this);    }}

/** * Created by laizhiyuan on 2017/8/1. * * * <p> *     设计模式-访问者模式-具体元素B * </p> */public class ConcreteElementB extends Element {    @Override    public void accept(Visitor visitor) {        visitor.visitConcreteElementB(this);    }}

/** * Created by laizhiyuan on 2017/8/1. * * <p> *     设计模式-访问者模式-访问者访问元素高层接口 * </p> */public class ObjectStructure {    private List<Element> elementList = new ArrayList<Element>();    public void attach(Element element){        elementList.add(element);    }    public void detach(Element element){        elementList.remove(element);    }    public void accept(Visitor visitor){        for (Element element : elementList){            element.accept(visitor);        }    }}

9、测试

/** * Created by laizhiyuan on 2017/8/1. */public class Client {    public static void main(String[] args) {        ObjectStructure structure = new ObjectStructure();        structure.attach(new ConcreteElementA());        structure.attach(new ConcreteElementB());        ConcreteVisitorA visitorA = new ConcreteVisitorA();        ConcreteVisitorB visitorB = new ConcreteVisitorB();        structure.accept(visitorA);        structure.accept(visitorB);    }}

10、控制台输出