设计模式之访问者模式
来源:互联网 发布:林彪军事才能 知乎 编辑:程序博客网 时间:2024/05/19 05:29
访问者模式(Visitor Pattern):在不改变某对象结构中元素的前提下,定义作用于这些元素的新操作。
访问者模式适用于数据结构相对稳定的系统,可以把数据结构和作用于结构上的操作解耦,使操作集合可以相对自由地变化。一种操作就相当于一个访问者。访问者模式将有关操作行为集中到一个访问者对象中。
访问者模式的缺点在于会使数据结构的变化变得困难。
比如男人和女人对于不同的事件有不同的反应,如果单纯抽象出Person基类,Man和Woman根据传递进来的不同事件作出不同反应,这样新增事件的话都要修改Man和Woman,违反了封闭开放原则。
可以把变化的地方,也就是不同的事件,抽象一个基类,然后基于这个基类进行扩展,可以达到比较好的解耦效果。
实例实现
首先定义数据基类,基本方法就是对事件进行反应:
public interface Person { void react(Event visitor);}
两个数据类,访问者模式一般应用于数据元素比较稳定的情况下:
class Man implements Person { @Override public void react(Event visitor) { visitor.getManReaction(this); }}class Woman implements Person { @Override public void react(Event visitor) { visitor.getWomanReaction(this); }}
此处用到一个技术叫双分派,就是在数据对象的一个方法中,接收事件对象作为参数,这是一次分派;然后接收到的事件对象调用自己的方法,传入调用它的数据对象作为方法参数,这就是第二次分派。双分派技术意味着方法的执行不仅取决于方法参数,还取决于执行方法的对象,由方法参数和调用者本身共同决定执行结果。
然后定义事件类,也就是模式里的访问者,事件类就是定义数据类各自的反应方法,如果数据元素稳定不变的话,事件类的方法也就不用去修改:
public interface Event { void getManReaction(Man man); void getWomanReaction(Woman woman);}
事件类的具体实现:
class Success implements Event { @Override public void getManReaction(Man man) { System.out.println(man.getClass().getSimpleName() + " " + this.getClass().getSimpleName() + "时,背后一般有个伟大的女人"); } @Override public void getWomanReaction(Woman woman) { System.out.println(woman.getClass().getSimpleName() + " " + this.getClass().getSimpleName() + "时,背后一般有个不成功的男人"); }}class Failure implements Event { @Override public void getManReaction(Man man) { System.out.println(man.getClass().getSimpleName() + " " + this.getClass().getSimpleName() + "时,独自借酒浇愁"); } @Override public void getWomanReaction(Woman woman) { System.out.println(woman.getClass().getSimpleName() + " " + this.getClass().getSimpleName() + "时,需要人来安慰"); }}class Marriage implements Event { @Override public void getManReaction(Man man) { System.out.println(man.getClass().getSimpleName() + " " + this.getClass().getSimpleName() + "时,我会照顾你一辈子"); } @Override public void getWomanReaction(Woman woman) { System.out.println(woman.getClass().getSimpleName() + " " + this.getClass().getSimpleName() + "时,我愿意和你到天荒地老"); }}
然后我们还可以定义一个数据结构,用来组织数据元素对于不同访问者的反应结果:
public class DataStructure { private List<Person> elements = new ArrayList<>(); public void addElement(Person element) { elements.add(element); } public void removeElement(Person element) { elements.remove(element); } public void showReaction(Event visitor) { for (Person person : elements) { person.react(visitor); } }}
测试类:
public class Main { public static void main(String[] args) { final DataStructure dataStructure = new DataStructure(); final Man man = new Man(); final Woman woman = new Woman(); dataStructure.addElement(man); dataStructure.addElement(woman); dataStructure.showReaction(new Success()); System.out.println(); dataStructure.showReaction(new Failure()); System.out.println(); dataStructure.showReaction(new Marriage()); }}
输出:
Man Success时,背后一般有个伟大的女人Woman Success时,背后一般有个不成功的男人Man Failure时,独自借酒浇愁Woman Failure时,需要人来安慰Man Marriage时,我会照顾你一辈子Woman Marriage时,我愿意和你到天荒地老
访问者模式使得数据元素不变的情况下,新增事件只要创建新的实现即可,不用修改原有代码,很好地符合了封闭开放原则。
阅读全文
0 0
- 设计模式之访问者
- 设计模式之访问者
- 设计模式之访问者模式
- 设计模式之--访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 【设计模式】之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 设计模式之访问者模式
- 每天一点MySQL-数据类型
- 批量文件重命名
- C++ 嵌入汇编 获取CPU信息
- 数据结构之图的遍历(BFS+DFS)
- java中Set以及常用子类
- 设计模式之访问者模式
- oracle中decode函数如何使用?
- Java书单
- ubuntu下安装配置QT
- React Native仿美团下拉菜单
- 学习UBOOT前奏之hardware-sdram[s3c2440]
- java 获取文件路径
- 3594: [Scoi2014]方伯伯的玉米田
- 剑指offer:二叉搜索树与双向链表