一、概念
访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的前提下定义作用于这些元素的操作。
二、类图及基本代码
//抽象访问者
public abstract class Visitor {
public abstract void VisitorConcreteElementA(ConcreteElementA concreteElementA);
public abstract void VisitorConcreteElementB(ConcreteElementB concreteElementB);
}
//具体访问者1
public class ConcreteVisitor1 extends Visitor{
@Override
public void VisitorConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
@Override
public void VisitorConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
}
//具体访问者2
public class ConcreteVisitor2 extends Visitor{
@Override
public void VisitorConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
@Override
public void VisitorConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName()+"被"+this.getClass().getSimpleName()+"访问");
}
}
//抽象元素
public abstract class Element {
public abstract void Accept(Visitor visitor);
}
//具体元素A
public class ConcreteElementA extends Element{
@Override
public void Accept(Visitor visitor) {
visitor.VisitorConcreteElementA(this);
}
}
//具体元素B
public class ConcreteElementB extends Element {
@Override
public void Accept(Visitor visitor) {
visitor.VisitorConcreteElementB(this);
}
}
//对象结构
public class ObjectStructure {
private List<Element> list = new ArrayList<>();
public void Attach(Element element) {
list.add(element);
}
public void Detach(Element element) {
list.remove(element);
}
public void Accept(Visitor visitor) {
for (Element element : list) {
element.Accept(visitor);
}
}
}
//客户端
public class Client {
public static void main(String[] args) {
ObjectStructure objectStructure=new ObjectStructure();
objectStructure.Attach(new ConcreteElementA());
objectStructure.Attach(new ConcreteElementB());
ConcreteVisitor1 v1=new ConcreteVisitor1();
ConcreteVisitor2 v2=new ConcreteVisitor2();
objectStructure.Accept(v1);
objectStructure.Accept(v2);
}
}
三、实例之男女区别
//抽象元素
public abstract class Person {
public abstract void Accept(Action action);
}
//男
public class Man extends Person{
@Override
public void Accept(Action action) {
action.GetManConclusion(this);
}
}
//女
public class Woman extends Person{
@Override
public void Accept(Action action) {
action.GetWomanConclusion(this);
}
}
//抽象状态类
public abstract class Action {
public abstract void GetManConclusion(Person man);
public abstract void GetWomanConclusion(Person woman);
}
//恋爱状态
public class Amativeness extends Action {
@Override
public void GetManConclusion(Person man) {
System.out.println("男人恋爱时");
}
@Override
public void GetWomanConclusion(Person woman) {
System.out.println("女人恋爱时");
}
}
//失败状态
public class Failing extends Action{
@Override
public void GetManConclusion(Person man) {
System.out.println("男人失败时");
}
@Override
public void GetWomanConclusion(Person woman) {
System.out.println("女人失败时");
}
}
//结婚状态
public class Marriage extends Action{
@Override
public void GetManConclusion(Person man) {
System.out.println("男人结婚时,,,,");
}
@Override
public void GetWomanConclusion(Person woman) {
System.out.println("女人结婚时,,,,");
}
}
//对象结构,用于访问男,女元素
public class ObjectStructure {
private List<Person> list = new ArrayList<>();
public void Attach(Person person) {
list.add(person);
}
public void Detach(Person person) {
list.remove(person);
}
public void Display(Action action) {
for (Person person : list) {
person.Accept(action);
}
}
}
public class Client {
public static void main(String[] args) {
ObjectStructure objectStructure=new ObjectStructure();
objectStructure.Attach(new Man());
objectStructure.Attach(new Woman());
Success success=new Success();
//看男人和女人在成功时的状态
objectStructure.Display(success);
//新增一个结婚状态
Marriage marriage=new Marriage();
objectStructure.Display(marriage);
}
}
四、总结
1、使用时机。
访问者模式适用于数据结构稳定,又有易于变化的算法。如男女区别案例中,人只有男,女之分,而男,女在不同的状态下具有不同的表现,这时使用访问者模式。
2、优点与缺点。
优点:易于增加新的操作,因为增加一个新操作就是增加一个新的访问者类。如男女区别案例中,新增一个结婚状态,只需新增一个结婚状态类即可。
缺点:增加新的数据结构比较困难。如果男女区别案例中,如果又有一个新的性别,那么就要修改很多类才能完成想要的功能,较为复杂。
Age wrinkles the body. Quitting wrinkles the soul.