人物:大鸟,小菜
事件:小菜和大鸟聊男人和女人的区别。小菜道,男人成功时,背后多半有一个伟大的女人,女人成功时,背后大多有一个不成功的男人;男人失败时,闷头喝酒,谁也不用劝,女人失败时,两眼汪汪,谁也劝不了;男人恋爱时,凡事不懂也要装懂,女人恋爱时,遇事懂也要装作不懂。大鸟道,既然你都这样说了,那我们今天就将男人女人和访问者模式一起,混着学。
访问者模式:
1.简介访问者模式
2.用访问者模式实现案例,并简述优缺点
访问者模式
1.概念:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
2.结构图:
男人女人案例结合访问者模式
1.访问者模式的前提:访问者模式适用于数据结构相对稳定的系统。即状态类抽象的稳定,因为类别只有男人和女人,所以状态类中抽象的方法时稳定的,如果有很多类别的话,每加一个类别,就需要在状态各个类中加一个方法,不符合开放封闭原则。
2.结构图:
3.代码示例:
Action状态的抽象类:
public abstract class Action { /** * 得到男人结论或反映 * * @param concreteElementA */ public abstract void getManConclusion(Man concreteElementA); /** * 得到女人结论或反映 * * @param concreteElementB */ public abstract void getWomanConclusion(Woman concreteElementB); }
Person类,人的抽象类:
@Data public abstract class Person { public abstract void accept(Action visitor); }
Success类,Failing类,Amativeness类,都是具体状态类:
@Slf4j public class Success extends Action { @Override public void getManConclusion(Man concreteElementA) { log.info("{}{}时,背后多半有一个伟大的女人", concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()); } @Override public void getWomanConclusion(Woman concreteElementB) { log.info("{}{}时,背后大多有一个不成功的男人", concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()); } }
@Slf4j public class Failing extends Action { @Override public void getManConclusion(Man concreteElementA) { log.info("{}{}时,闷头喝酒,谁也不用劝", concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()); } @Override public void getWomanConclusion(Woman concreteElementB) { log.info("{}{}时,两眼汪汪,谁也劝不了", concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()); } }
@Slf4j public class Amativeness extends Action { @Override public void getManConclusion(Man concreteElementA) { log.info("{}{}时,凡事不懂也要装懂", concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()); } @Override public void getWomanConclusion(Woman concreteElementB) { log.info("{}{}时,遇事懂也要装作不懂", concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()); } }
Man类和Woman类,男人类和女人类:
public class Man extends Person { @Override public void accept(Action visitor) { visitor.getManConclusion(this); } }
public class Woman extends Person { @Override public void accept(Action visitor) { visitor.getWomanConclusion(this); } }
ObjectStructure类,用来针对不同的状态,来遍历男人女人,从而得到不同的反映:
public class ObjectStructure { private List<Person> elements = new ArrayList<Person>(); public void attach(Person element) { elements.add(element); } public void detach(Person element) { elements.remove(element); } public void display(Action vistor) { for (Person person : elements) { person.accept(vistor); } } }
客户端代码:
public class StatusClient { public static void main(String[] args) { ObjectStructure o = new ObjectStructure(); o.attach(new Man()); o.attach(new Woman()); //成功时的反映 Success v1 = new Success(); o.display(v1); //失败时的反映 Failing v2 = new Failing(); o.display(v2); //恋爱时的反映 Amativeness v3 = new Amativeness(); o.display(v3); } }
4.好处和不足
(1)好处:扩展性好,可以在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能,符合开放封闭原则,符合单一职责原则。
(2)不足:违反了迪米特原则,因为具体元素对访问者公布细节,违反了依赖倒置原则,依赖了具体类,没有依赖抽象;对象结构变化困难,若对象结构发生了改变,访问者的接口和访问者的实现也都要发生相应的改变。