设计模式-访问者模式(Visitor Pattern)

581 阅读4分钟

Github 源码地址

23种设计模式总览

创建型模式

结构型模式

行为型模式

定义

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

优缺点

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

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

使用场景

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

实现

我们可以通过生活中的一些例子来理解它,比如家里来了客人,客人就是访问者,他可以做一些事情,但是又不能做全部的事情; 又或者说去网吧上网的小明,小明也是访问者,他可以在网吧玩游戏、看视频、听音乐等等,但是不能破坏网吧中的设备等等。按照这么理解,我们大概就可以知道访问者模式主要是做什么了。

访问者模式主要由这五个角色组成,抽象访问者(Visitor)、具体访问者(ConcreteVisitor)、抽象节点(Node)、具体节点(ConcreteNode)和结构对象(ObjectStructure)。

  • 抽象访问者(Visitor)角色:声明了一个或者多个方法操作,形成所有的具体访问者角色必须实现的接口。
  • 具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。
  • 抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参数。
  • 具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。
  • 结构对象(ObjectStructure)角色:有如下的责任,可以遍历结构中的所有元素。

我们使用一个简单的示例来加以说明。 图书馆有一台电脑,但是只能玩游戏和看图片。张三和李四先后使用了这台电脑,那么他们就可以当作是访问者。 首先定义一个抽象的访问者,拥有玩游戏和看图片的方法;然后再定义一个抽象节点电脑,接受这个请求。

抽象访问者(Visitor)角色

//抽象访问者(Visitor)角色
interface Visitor {
    //可以访问游戏
    void visit(Games games);

    //可以访问图片
    void visit(Photos photos);
}

抽象节点(Node)角色

//抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参数。
interface Computer {
    void accept(Visitor visitor);
}

具体节点(ConcreteNode)角色

//具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。
class Games implements Computer {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String play() {
        return "play Games";
    }
}
//具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。
class Photos implements Computer {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String watch() {
        return "watch photos";
    }
}

结构对象(ObjectStructure)角色

//结构对象(ObjectStructure)角色:有如下的责任,可以遍历结构中的所有元素。
class ObjectStructure {

    private List<Computer> computers = new ArrayList<Computer>();

    public void action(Visitor visitor) {
        for (Computer c : computers) {
            c.accept(visitor);
        }
    }

    public void add(Computer computer) {
        computers.add(computer);
    }
}

验证结果

class Test {
    public static void main(String[] args) {
        // 创建一个结构对象
        ObjectStructure os = new ObjectStructure();
        // 给结构增加一个节点
        os.add(new Games());
        // 给结构增加一个节点
        os.add(new Photos());
        
        // 创建2个访问者
        Visitor visitorZhangSan = new PersonVisitor("zhangsan");
        Visitor visitorLisi = new PersonVisitor("lisi");
        
        os.action(visitorZhangSan);
        os.action(visitorLisi);
    }
}
zhangsan-----play Games
zhangsan-----watch photos
lisi-----play Games
lisi-----watch photos