设计模式:018_访问者模式

66 阅读3分钟

访问者模式

访问者模式是一种将数据结构和数据操作分离的设计模式,解决数据结构和操作数据耦合性的问题。

作用

  • 符合单一职责原则。
  • 优秀的扩展性和灵活性,新增访问者和元素都比较方便。
  • 访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

缺点

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

适用场景

  • 对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。

类图

访问者模式类图.png

Visitor:访问者接口或者抽象类

定义了对每个 Element 访问的行为,它的参数就是被访问的元素。 它的方法个数理论上与元素的个数是一样的,因此,访问者模式要求元素的类型要稳定。 如果经常添加、移除元素类,必然会导致频繁地修改 Visitor 接口,如果出现这种情况,则说明不适合使用访问者模式。

ConcreteVisitor:具体的访问者

它需要给出对每一个元素类访问时所产生的具体行为。

Element:元素接口或者抽象类

它定义了一个接受访问者(accept)的方法,其意义是指每一个元素都要可以被访问者访问。

ConcreteElement:具体的元素类

它提供接受访问的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。

ObjectStructure:定义当中所提到的对象结构

对象结构是一个抽象表述,它内部管理了元素集合,并且可以迭代这些元素提供访问者访问。

代码表达

双重分派

  • 客户端将访问者作为参数传递到元素具体子类
  • 然后在元素具体子类中,将自己(this)作为参数,调用具体访问者中的方法
// Visitor:访问者接口或者抽象类
public abstract class Action {
    public abstract void getManResult(Man man);
    public abstract void getWomanResult(Woman woman);
}
// ConcreteVisitor:具体的访问者
public class Success extends Action {
    @Override
    public void getManResult(Man man) {
        System.out.println("man result:Success");
    }

    @Override
    public void getWomanResult(Woman woman) {
        System.out.println("woman result:Success");
    }
}

public class Fail extends Action {
    @Override
    public void getManResult(Man man) {
        System.out.println("man result:Fail");
    }

    @Override
    public void getWomanResult(Woman woman) {
        System.out.println("woman result:Fail");
    }
}
// Element:元素接口或者抽象类
public abstract class Person {
    private boolean isActionFinish = false;

    public abstract void accept(Action action);

    public void actionFinish() {
        isActionFinish = true;
    }

    public boolean getActionFinish() {
        return isActionFinish;
    }
}
// ConcreteElement:具体的元素类
public class Man extends Person {
    @Override
    public void accept(Action action) {
        if (!getActionFinish()) {
            action.getManResult(this);
            actionFinish();
        }
    }
}

public class Woman extends Person {
    @Override
    public void accept(Action action) {
        if (!getActionFinish()) {
            action.getWomanResult(this);
            actionFinish();
        }
    }
}
// ObjectStructure:对象结构类,内部管理了元素集合
public class ObjectStructure {
    // 内部管理了元素集合
    private List<Person> list = new LinkedList<>();

    public void add(Person person) {
        list.add(person);
    }

    public void remove(Person person) {
        list.remove(person);
    }

    public void showResult(Action action) {
        for (Person person : list) {
            person.accept(action);
        }
    }
}

客户端调用

ObjectStructure structure = new ObjectStructure();
structure.add(new Woman());
structure.add(new Woman());
Success success = new Success();
structure.showResult(success);

structure.add(new Man());
structure.add(new Man());
Fail fail = new Fail();
structure.showResult(fail);