设计模式-行为型之访问者模式
2015-09-18 22:04
190 查看
模式动机
在实际使用时,对同一集合对象的操作并不是唯一的,对相同的元素对象可能存在多种不同的操作方式。而且这些操作方式并不稳定,可能还需要增加新的操作,以满足新的业务需求。此时,我们可以考虑访问者模式,访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式。模式定义
表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。模式结构
抽象访问者:Vistor,定义访问操作visit()
具体访问者:ConcreteVisitor
抽象元素:Element,定义被访问操作accept()
具体元素 : ConcreteElement
对象结构:ObjectStructure,负责存储了不同类型的元素对象,以供不同访问者访问。
代码示例
顾客在超市中将选购商品,如肉、图书等放在购物车中,然后到收银员处付款。在购物过程中,顾客需要对这些商品进行访问,以便确认这些商品的质量,之后收银员计算价格时也需要访问购物车的商品。此时,购物车作为一个ObjectStructure(对象结构)用于存储各种类型的商品,而顾客和收银员作为访问这些商品的访问者。不同类型的商品其访问形式也可能不同,如肉需要过秤之后再计价,而图书不需要。使用访问者模式来设计该购物过程。//抽象元素类-商品 public interface Goods { public void accept(Visitor visitor); }
//具体元素类-图书 public class Book implements Goods{ @Override public void accept(Visitor visitor) { visitor.visit(this); } }
//具体元素类-肉 public class Meat implements Goods{ @Override public void accept(Visitor visitor) { visitor.visit(this); } }
//抽象访问者 public abstract class Visitor { public abstract void visit(Book book); public abstract void visit(Meat meat); }
//具体访问者-售货员 public class Saler extends Visitor{ @Override public void visit(Book book) { System.out.println("售货员扫码,查看书的价格"); } @Override public void visit(Meat meat) { System.out.println("售货员称重,查看肉的价格"); } }
//具体访问者-消费者 public class Customer extends Visitor{ @Override public void visit(Book book) { System.out.println("消费者查看书的内容,看是否精彩"); } @Override public void visit(Meat meat) { System.out.println("消费者查看肉的肥瘦、新鲜程度等"); } }
//对象结构-购物车 import java.util.ArrayList; import java.util.List; public class ShoppingCart { private List<Goods> goodsList = new ArrayList<Goods>(); public void addGoods(Goods goods){ goodsList.add(goods); } public void remove(Goods goods){ goodsList.remove(goods); } public void accept(Visitor visitor){ for(Goods goods:goodsList){ goods.accept(visitor); } } }
//客户端测试 public class Client { public static void main(String[] args) { Goods book = new Book(); Goods meat = new Meat(); ShoppingCart shoppingCart = new ShoppingCart(); shoppingCart.addGoods(book); shoppingCart.addGoods(meat); Visitor saler = new Saler(); Visitor customer = new Customer(); shoppingCart.accept(saler); shoppingCart.accept(customer); } }
控制台输出
售货员扫码,查看书的价格 售货员称重,查看肉的价格 消费者查看书的内容,看是否精彩 消费者查看肉的肥瘦、新鲜程度等
总结
在访问者模式中,相同的访问者可以以不同的方式访问不同的元素,相同的元素可以接受不同访问者以不同访问方式访问。在访问者模式中,增加新的访问者无须修改原有系统,系统具有较好的可扩展性。但增加一个新的元素类都需要要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。访问者模式包含五个角色:抽象访问者为对象结构类中每一个抽象元素类声明一个访问操作;具体访问者实现了每个由抽象访问者声明的操作,每一个操作用于访问对象结构中一种类型的元素;抽象元素一般是抽象类或者接口,它定义一个accept()方法,该方法以一个抽象访问者作为参数;具体元素实现了accept()方法,在其accept()中调用访问者的访问方法以便完成对一个元素的操作;对象结构是一个元素的集合,它用于存放元素对象,并且提供了遍历其内部元素的方法。
相关文章推荐
- __FILE__ php解析
- [LeetCode]题解(python):015-3Sum
- 斐波那契数列(有疑问)
- Spring Boot中实现Quartz动态定时任务
- 好的技术领导与差的技术领导,千万不要对号入座,你会死的很惨!
- 服务端控件
- Postgresql 创建空间数据库 支持geometry类型
- 结对项目,贪吃蛇
- iOS开发-方法调用在运行时的过程
- ADO.NET 概述
- 一个好的开端
- struts2--关于action的几种方法
- [转] - JAR文件包及jar命令详解 ( MANIFEST.MF的用法 )
- 算法积累:解决如何获取指定文件夹路径或者文件路径下所有子文件后缀为.h .m .c的文本的行数
- 切西瓜
- POJ 2774 最长公共子串
- NetworkStateReceiver的简单应用
- HDU 4003 Find Metal Mineral (树形DP,经典)
- 漫步云中网络
- centos 源代码安装nginx