访问者模式是什么?
表示一个作用于某对象结构中的各元素的操作,它使你可以再不改变各元素的类的前提下定义作用于这些元素的新操作
访问者模式解决什么问题?
男女在不同情境下表现的不同
abstract class Person {protected String action;public String getAction() {return action;}public void setAction(String action) {this.action = action;}public abstract void getConclusion();
}class Man extends Person {@Overridepublic void getConclusion() {if ("逛街".equals(action)) {System.out.println(this.getClass().getSimpleName() + action + "买完就走");} else if ("吃饭".equals(action)) {System.out.println(this.getClass().getSimpleName() + action + "狼吞虎咽");}}
}class Woman extends Person {@Overridepublic void getConclusion() {if ("逛街".equals(action)) {System.out.println(this.getClass().getSimpleName() + action + "到处乱逛");} else if ("吃饭".equals(action)) {System.out.println(this.getClass().getSimpleName() + action + "细嚼慢咽");}}
}
使用时
List<Person> personList = new ArrayList<>();Man man = new Man();
man.setAction("逛街");
personList.add(man);Woman woMan = new Woman();
woMan.setAction("逛街");
personList.add(woMan);for (Person person : personList) {person.getConclusion();
}
当要新增新的Action时,要修改两者的代码
访问者模式实现
创建不同的表现
abstract class Action {abstract void getManConclusion(Man concreteElementA);abstract void getWomanConclusion(Woman concreteElementB);
}class Shopping extends Action {@Overridevoid getManConclusion(Man concreteElementA) {System.out.println(concreteElementA.getClass().getSimpleName() + " " + getClass().getSimpleName() + "买完就走");}@Overridevoid getWomanConclusion(Woman concreteElementB) {System.out.println(concreteElementB.getClass().getSimpleName() + " " + getClass().getSimpleName() + "到处乱逛");}
}class eat extends Action {@Overridevoid getManConclusion(Man concreteElementA) {System.out.println(concreteElementA.getClass().getSimpleName() + " " + getClass().getSimpleName() + "狼吞虎咽");}@Overridevoid getWomanConclusion(Woman concreteElementB) {System.out.println(concreteElementB.getClass().getSimpleName() + " " + getClass().getSimpleName() + "细嚼慢咽");}
}
创建男女,这里采用双分派,先将Action作为传递给男/女,再将男/女作为参数传入给Action,意味着执行结果取决于两个调用者的类型
abstract class Person {abstract void accept(Action visitor);
}class Man extends Person {@Overridevoid accept(Action visitor) {visitor.getManConclusion(this);}
}class Woman extends Person {@Overridevoid accept(Action visitor) {visitor.getWomanConclusion(this);}
}
创建对象结构统一管理和遍历
class ObjStructure {private List<Person> mPersonList = new ArrayList<>();public void attach(Person person) {mPersonList.add(person);}public void detach(Person person) {mPersonList.remove(person);}public void display(Action visitor) {for (Person person : mPersonList) {person.accept(visitor);}}
}
调用时
ObjStructure objStructure = new ObjStructure();objStructure.attach(new Man());objStructure.attach(new Woman());objStructure.display(new Shopping());objStructure.display(new eat());
- 当要增加Action时,只需要新增一个类和修改上面的代码
- 但是如果新增一个外星人的话,就要在每个Action中新增对应方法,故访问者模式适用于数据结构稳定但算法易变化的情况