访问者模式(二十一)

一、定义

    封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。


二、类图及角色


1. Visitor 抽象访问者

    抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是 visit 方法的参数定义哪些对象是可以被访问的。

public interface IVisitor {
    // 可以访问哪些对象
    public void visit(ConcreteElement1 el1);
    public void visit(ConcreteElement2 el2);
}
2. ConcreteVisitor 具体访问者

    Visitor 的实现类,定义一个访问者访问到对象后需要做哪些事情。

public class Visitor implements IVisitor {
    // 访问el1元素
    public void visit(ConcreteElement1 el1) {
        el1.doSomething();
    }
    // 访问el2元素
    public void visit(ConcreteElement2 el2) {
        el2.doSomething();
    }
}
3. Element 抽象元素

    接口或者抽象类,声明接受哪一类访问者访问,程序上是通过 accept 的参数来定义的。

public abstract class Element {
    // 定义业务逻辑
    public abstract void doSomething();
    // 允许谁来访问
    public abstract void accept(IVisitor visitor);
}
4. ConcreteElement 具体元素

    实现 accept 方法,通常是 visitor.visit(this),基本上已经是默认的写法了。

public class ConcreteElement1 extends Element{
    // 完善业务逻辑
    public void doSomething(){
        // 业务处理
    }
    // 允许那个访问者访问
    public void accept(IVisitor visitor){
        visitor.visit(this);
    }
}
 
public class ConcreteElement2 extends Element{
    // 完善业务逻辑
    public void doSomething(){
        // 业务处理
    }
    // 允许那个访问者访问
    public void accept(IVisitor visitor){
        visitor.visit(this);
    }
}
5. ObjectStructure 结构对象

    提供一个高层接口以供访问者访问其中的元素,一般很少抽象出去,通常是一个集合,例如 List、Set、Map 等。

public class ObjectStruture {
    //对象生成器,这里通过一个工厂方法模式模拟
    public static Element createElement() {
        Random rand = new Random();
        if(rand.nextInt(100) > 50){
            return new ConcreteElement1();
        } else {
            return new ConcreteElement2();
        }
    }
}
6. 模拟一个场景
public class Client {
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            //获得元素对象
            Element e = ObjectStruture.createElement();
            //接受访问者访问
            e.accept(new Visitor());
        }
    }
}


三、优缺点

  • 优点
  1. 符合单一职责原则
    访问者和被访问者独立分开,各自负责各自的角色和职责。
  2. 优秀的扩展性
    元素类可以通过接受不同的访问者就可以实现不同操作的扩展。
  • 缺点
  1. 元素类对访问者是公布细节的
    访问者要访问一个类必然要求这个类公布一些方法和属性,这一点是迪米特法则(最少知道法则)不建议的。
  2. 违背了依赖倒置原则
    访问者依赖的都是具体元素,而不是抽象元素,抛弃了对接口的依赖,而是直接依赖实现类,扩展比较难。


四、使用场景

  1. 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。访问者模式使得你可以将相关的操作集中起来定义在一个类中。
  3. 当该对象结构被很多应用共享时,用访问者模式让每个应用仅包含需要用到的操作。
  4. 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。


查看更多:设计模式分类以及六大设计原则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值