java中的访问者模式学习
2015-08-01 10:53
549 查看
访问者模式是一种行为设计模式。访问者模式被用在针对一组相同类型对象的操作。优点是,可以把针对此对象的操作逻辑转移到另外一个类上。
例如,思考一下添加不同类型商品的购物车,当点击结算的时候,它计算出所有不同商品需付的费用。现在,计算逻辑即为计算这些不同类型商品的价格。或者说通过访问者模式我们把此逻辑转移到了另外一个类上面。让我们实现这个访问者模式的例子。
为了实现访问者模式,最先需要做的是创建能够被添加到购物车中代表不同类型商品(itemElement)的类。
注意,accept方法接受访问者作为参数。当然这儿还有其他的一些方法来指定详细的商品,但为了简化,此处没用过多的考虑细节,只关注访问者模式。
现在创建一些不同商品的实体类。
注意,accept()方法的实现是在实体类中,它调用访问者的visit()方法传递当前类对象作为自己的参数。
此处针对不同类型的商品所使用的visit()方法将会在访问者接口的实体类中被实现。
现在将实现访问者接口以及每种商品自己计算自己费用的逻辑。
现在看一看在程序中如何使用它。
当运行上述程序是,我们得到如下输出。
请注意,此处的实现,好像accept()方法对于所有商品是相同的,但是他也可以不同。例如,如果商品为空它能进行逻辑检查并不再调用visit()方法。
此模式的优点就是,如果操作的逻辑改变,我们只需要改变访问者的实现就够了,而不用去修改其他所有的商品类。
另一个好处是,添加新类别的商品到系统变得容易。只需要改变一下访问者接口以及其实现。已经存在的商品类别不会被干扰影响。
当然,访问者模式的缺点也需要知道,visit()方法的返回值的类型在设计系统式就需要明确。不然,就需要修改访问者的接口以及所有接口实现。另外如果访问者接口的实现太多,系统的扩展性就会下降。
转载:http://ifeve.com/visitor-design-pattern-in-java-example-tutorial/
案例源码下载:http://download.csdn.net/detail/ma20120607/8951193
例如,思考一下添加不同类型商品的购物车,当点击结算的时候,它计算出所有不同商品需付的费用。现在,计算逻辑即为计算这些不同类型商品的价格。或者说通过访问者模式我们把此逻辑转移到了另外一个类上面。让我们实现这个访问者模式的例子。
为了实现访问者模式,最先需要做的是创建能够被添加到购物车中代表不同类型商品(itemElement)的类。
ItemElement.java
1 | package com.journaldev.design.visitor; |
2 |
3 | public interface ItemElement { |
4 |
5 | public int accept(ShoppingCartVisitor visitor); |
6 | } |
现在创建一些不同商品的实体类。
Book.java
01 | package com.journaldev.design.visitor; |
02 |
03 | public class Book implements ItemElement { |
04 |
05 | private int price; |
06 | private String isbnNumber; |
07 |
08 | public Book( int cost, String isbn){ |
09 | this .price=cost; |
10 | this .isbnNumber=isbn; |
11 | } |
12 |
13 | public int getPrice() { |
14 | return price; |
15 | } |
16 |
17 | public String getIsbnNumber() { |
18 | return isbnNumber; |
19 | } |
20 |
21 | @Override |
22 | public int accept(ShoppingCartVisitor visitor) { |
23 | return visitor.visit( this ); |
24 | } |
25 |
26 | } |
Fruit.java
01 | package com.journaldev.design.visitor; |
02 |
03 | public class Fruit implements ItemElement { |
04 |
05 | private int pricePerKg; |
06 | private int weight; |
07 | private String name; |
08 |
09 | public Fruit( int priceKg, int wt, String nm){ |
10 | this .pricePerKg=priceKg; |
11 | this .weight=wt; |
12 | this .name = nm; |
13 | } |
14 |
15 | public int getPricePerKg() { |
16 | return pricePerKg; |
17 | } |
18 |
19 | public int getWeight() { |
20 | return weight; |
21 | } |
22 |
23 | public String getName(){ |
24 | return this .name; |
25 | } |
26 |
27 | @Override |
28 | public int accept(ShoppingCartVisitor visitor) { |
29 | return visitor.visit( this ); |
30 | } |
31 |
32 | } |
此处针对不同类型的商品所使用的visit()方法将会在访问者接口的实体类中被实现。
ShoppingCartVisitor.java
1 | package com.journaldev.design.visitor; |
2 |
3 | public interface ShoppingCartVisitor { |
4 |
5 | int visit(Book book); |
6 | int visit(Fruit fruit); |
7 | } |
ShoppingCartVisitorImpl.java
01 | package com.journaldev.design.visitor; |
02 |
03 | public class ShoppingCartVisitorImpl implements ShoppingCartVisitor { |
04 |
05 | @Override |
06 | public int visit(Book book) { |
07 | int cost= 0 ; |
08 | //apply 5$ discount if book price is greater than 50 |
09 | if (book.getPrice() > 50 ){ |
10 | cost = book.getPrice()- 5 ; |
11 | } else cost = book.getPrice(); |
12 | System.out.println( "Book ISBN::" +book.getIsbnNumber() + " cost =" +cost); |
13 | return cost; |
14 | } |
15 |
16 | @Override |
17 | public int visit(Fruit fruit) { |
18 | int cost = fruit.getPricePerKg()*fruit.getWeight(); |
19 | System.out.println(fruit.getName() + " cost = " +cost); |
20 | return cost; |
21 | } |
22 |
23 | } |
ShoppingCartClient.java
01 | package com.journaldev.design.visitor; |
02 |
03 | public class ShoppingCartClient { |
04 |
05 | public static void main(String[] args) { |
06 | ItemElement[] items = new ItemElement[]{ new Book( 20 , "1234" ), new Book( 100 , "5678" ), |
07 | new Fruit( 10 , 2 , "Banana" ), new Fruit( 5 , 5 , "Apple" )}; |
08 |
09 | int total = calculatePrice(items); |
10 | System.out.println( "Total Cost = " +total); |
11 | } |
12 |
13 | private static int calculatePrice(ItemElement[] items) { |
14 | ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl(); |
15 | int sum= 0 ; |
16 | for (ItemElement item : items){ |
17 | sum = sum + item.accept(visitor); |
18 | } |
19 | return sum; |
20 | } |
21 |
22 | } |
1 | Book ISBN:: 1234 cost = 20 |
2 | Book ISBN:: 5678 cost = 95 |
3 | Banana cost = 20 |
4 | Apple cost = 25 |
5 | Total Cost = 160 |
访问者模式用例图
访问者模式的类图实现如下:此模式的优点就是,如果操作的逻辑改变,我们只需要改变访问者的实现就够了,而不用去修改其他所有的商品类。
另一个好处是,添加新类别的商品到系统变得容易。只需要改变一下访问者接口以及其实现。已经存在的商品类别不会被干扰影响。
当然,访问者模式的缺点也需要知道,visit()方法的返回值的类型在设计系统式就需要明确。不然,就需要修改访问者的接口以及所有接口实现。另外如果访问者接口的实现太多,系统的扩展性就会下降。
转载:http://ifeve.com/visitor-design-pattern-in-java-example-tutorial/
案例源码下载:http://download.csdn.net/detail/ma20120607/8951193
相关文章推荐
- Eclipse最全快捷键
- Java运算符优先级
- Java中的数值数据、原码、反码、补码、数据类型及范围、字面量
- 浅析Java中的访问权限控制
- Struts2 Hello World 实例
- Spring+Struts2+mybatis三大框架的整合配置
- java学习第二天笔记
- Eclipse常用快捷键大全
- Java集合源码解读(一):集合总体框架
- struts2学习笔记(五)值栈与ognl
- eclipse 配置maven插件 以及nuxus 搭建本地私服仓库
- 轻松java学习之路1
- Java注解的使用
- spring mvc 导出 excel
- java二叉树创建的第二种模型
- java 基础知识2
- JAVA 并发编程-线程同步通信技术(Lock和Condition)(十)
- strust2文件上传
- Java基础知识(上)
- 定制Eclipse IDE之功能篇(一)