Java 设计模式Java设计模式

Java设计模式 - 访问者模式

2019-03-24  本文已影响4人  a57ecf3aaaf2

定义

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

看到其定义,确实感到访问者模式的复杂。砍死简单的访问者模式其实是23种设计模式中最难的一个。简单来说,访问者模式就是一种将数据操作与数据结构分离的设计模式。

大多数情况下,我们基本上用不到访问者模式,但是一旦需要用上它,会带来意想不到的效果。

示例

首先,定义一个抽象访问者:

public interface IVisitor {
    void visit(Manager manager);
    void visit(CommonStaff staff);
}

定义具体的访问者,用于访问被访问者的年龄、姓名:

public class AgeVisitor implements IVisitor {

    @Override
    public void visit(Manager manager) {
        System.out.println("Manager 的年龄: " + manager.getAge());
    }

    @Override
    public void visit(CommonStaff staff) {
        System.out.println("CommonStaff 的年龄: " + staff.getAge());
    }
}
public class NameVisitor implements IVisitor {

    @Override
    public void visit(Manager manager) {
        System.out.println("Manager 的姓名: " + manager.getName());
    }

    @Override
    public void visit(CommonStaff staff) {
        System.out.println("Manager 的姓名: " + staff.getName());
    }
}

定义一个抽象访问者员工类型的接口:

public interface Staff {
    void accept(IVisitor visitor);
}

员工分为普通员工和管理层:

public class CommonStaff implements Staff {

    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }

    public int getAge() {
        return 22;
    }

    public String getName() {
        return "ddd";
    }
}
public class Manager implements Staff {

    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }

    public int getAge() {
        return 22;
    }

    public String getName() {
        return "ddd";
    }
}

最终实现:

public class Lists {

    private List<IVisitor> list = new ArrayList<>();

    public void add(IVisitor staff) {
        list.add(staff);
    }

    public void visit(Staff staff) {
        for (int i = 0; i < list.size(); i++) {
            staff.accept(list.get(i));
        }
    }

}
public class Client {

    public static void main(String[] args) {

        CommonStaff cs = new CommonStaff();
        Manager m = new Manager();

        IVisitor ageVisitor = new AgeVisitor();
        IVisitor nameVisitor = new NameVisitor();

        Lists lists = new Lists();
        lists.add(ageVisitor);
//        lists.add(nameVisitor);

        lists.visit(cs);
        lists.visit(m);
    }
}

到此为止,访问者模式的结构已经清晰地通过代码展示出来了。对于访问者模式来说,如果不是为业务需求而生,就没必要使用访问者模式,虽然访问者模式有着优秀的对数据结构新的扩展操作,但是同时也有着明显的缺点。

访问者模式的优缺点

优点
1. 访问者和被访问者各司其职,角色单一,符合单一职责原则。
2. 优秀的访问者扩展性。上面的代码可通过增加一个访问者子类,轻易实现扩展。

缺点
1. 被访问者的内部细节对访问者公布,违反了迪米特原则。
2. 访问者依赖的是具体被访问者,而非抽象被访问者,因其需要对具体被访问者做不同操作,违反了依赖倒置原则。
3. 具体元素的变更扩展较困难。上面的示例中,如果在抽象访问者中新增一个 sex 属性,那么访问者势必要做出修改,如果有多个访问者,这种变更就会变得复杂。

访问者模式的应用场景

1. 被访问者内部结构稳定,元素简单不易变化,但需要对其进行结构上的新操作。
2. 业务规则要求遍历多个不同的对象。与迭代器模式的不同点是,迭代器模式访问的是相同基类或接口的对象,而访问者模式面对的是不同类型的对象(也就是说,上面示例中的员工类可以不实现相同的基类 Staff)。其实,访问者模式是迭代器模式的一种特殊扩展。

本文由 Fynn_ 原创,未经许可,不得转载!

上一篇 下一篇

猜你喜欢

热点阅读