访问者模式
定义
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
UML图
特点
- 访问者模式适用于数据结构相对稳定的系统,它把数据和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化
- 访问者模式的目的是要把处理从数据结构分离出来
- 如果有比较稳定的数据结构,又易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易
- 访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中
- 访问者的缺点其实也就是使增加新的数据结构变得困难。
举个栗子
人,分为男人和女人,分别描述他/她成功、失败、恋爱时的不同原因。。。
UML图
Talk is cheap, show me the code
(屁话少说,放码过来)
/**
* 状态
* Created by callmeDevil on 2019/12/22.
*/
public abstract class Action {
// 得到男人结论或反应
public abstract void getManConclusion(Man concreteElementA);
// 得到女人结论或反应
public abstract void getWomanConclusion(Woman concreteElementB);
}
/**
* 成功
* Created by callmeDevil on 2019/12/22.
*/
public class Success extends Action {
@Override
public void getManConclusion(Man concreteElementA) {
System.out.println(String.format("%s %s时,背后多半有一个伟大的女人。",
concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
@Override
public void getWomanConclusion(Woman concreteElementB) {
System.out.println(String.format("%s %s时,背后多半有一个不成功的男人。",
concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
}
/**
* 失败
* Created by callmeDevil on 2019/12/22.
*/
public class Failing extends Action {
@Override
public void getManConclusion(Man concreteElementA) {
System.out.println(String.format("%s %s时,背后多半有一个不伟大的女人。",
concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
@Override
public void getWomanConclusion(Woman concreteElementB) {
System.out.println(String.format("%s %s时,背后多半有一个成功的男人。",
concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
}
/**
* 恋爱
* Created by callmeDevil on 2019/12/22.
*/
public class Amativeness extends Action {
@Override
public void getManConclusion(Man concreteElementA) {
System.out.println(String.format("%s %s时,背后多半是个高富帅。",
concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
@Override
public void getWomanConclusion(Woman concreteElementB) {
System.out.println(String.format("%s %s时,背后多半是个会打扮。",
concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}
}
/**
* 人
* Created by callmeDevil on 2019/12/22.
*/
public abstract class Person {
// 接受
public abstract void accept(Action visitor);
}
/**
* 男人
* Created by callmeDevil on 2019/12/22.
*/
public class Man extends Person{
@Override
public void accept(Action visitor) {
// 首先在客户端程序中将具体状态作为参数传递给“男人”类完成了一次分派,然后“男人”类调用
// 作为参数的“具体状态”中的方法“男人反应”,同时将自己(this)作为参数传递进去,这便完成
// 了第二次分派。这种技术手段称为“双分派”。
visitor.getManConclusion(this);
}
}
/**
* 女人
* Created by callmeDevil on 2019/12/22.
*/
public class Woman extends Person{
@Override
public void accept(Action visitor) {
visitor.getWomanConclusion(this);
}
}
/**
* 对象结构
* Created by callmeDevil on 2019/12/22.
*/
public class ObjectStructure {
private List<Person> elements = new ArrayList<>();
// 增加
public void attach(Person element) {
elements.add(element);
}
// 移除
public void detach(Person element) {
elements.remove(element);
}
// 查看显示
public void display(Action visitor) {
for (Person element : elements) {
element.accept(visitor);
}
}
}
public class Test {
public static void main(String[] args) {
ObjectStructure obj = new ObjectStructure();
// 对象结构中加入要对比的男人和女人
obj.attach(new Man());
obj.attach(new Woman());
// 成功的反应
Success success = new Success();
obj.display(success);
// 失败的反应
Failing failing = new Failing();
obj.display(failing);
// 恋爱的反应
Amativeness amativeness = new Amativeness();
obj.display(amativeness);
}
}
运行结果
Man Success时,背后多半有一个伟大的女人。
Woman Success时,背后多半有一个不成功的男人。
Man Failing时,背后多半有一个不伟大的女人。
Woman Failing时,背后多半有一个成功的男人。
Man Amativeness时,背后多半是个高富帅。
Woman Amativeness时,背后多半是个会打扮。