您的位置:首页 > 编程语言 > Java开发

java中的访问者模式学习

2015-08-01 10:53 549 查看
访问者模式是一种行为设计模式。访问者模式被用在针对一组相同类型对象的操作。优点是,可以把针对此对象的操作逻辑转移到另外一个类上。

例如,思考一下添加不同类型商品的购物车,当点击结算的时候,它计算出所有不同商品需付的费用。现在,计算逻辑即为计算这些不同类型商品的价格。或者说通过访问者模式我们把此逻辑转移到了另外一个类上面。让我们实现这个访问者模式的例子。

为了实现访问者模式,最先需要做的是创建能够被添加到购物车中代表不同类型商品(itemElement)的类。


ItemElement.java

1
package
com.journaldev.design.visitor;
2
3
public
interface
ItemElement
{
4
5
public
int
accept(ShoppingCartVisitor
visitor);
6
}
注意,accept方法接受访问者作为参数。当然这儿还有其他的一些方法来指定详细的商品,但为了简化,此处没用过多的考虑细节,只关注访问者模式。

现在创建一些不同商品的实体类。

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
}
注意,accept()方法的实现是在实体类中,它调用访问者的visit()方法传递当前类对象作为自己的参数。

此处针对不同类型的商品所使用的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
请注意,此处的实现,好像accept()方法对于所有商品是相同的,但是他也可以不同。例如,如果商品为空它能进行逻辑检查并不再调用visit()方法。

访问者模式用例图

访问者模式的类图实现如下:



此模式的优点就是,如果操作的逻辑改变,我们只需要改变访问者的实现就够了,而不用去修改其他所有的商品类。

另一个好处是,添加新类别的商品到系统变得容易。只需要改变一下访问者接口以及其实现。已经存在的商品类别不会被干扰影响。

当然,访问者模式的缺点也需要知道,visit()方法的返回值的类型在设计系统式就需要明确。不然,就需要修改访问者的接口以及所有接口实现。另外如果访问者接口的实现太多,系统的扩展性就会下降。

转载:http://ifeve.com/visitor-design-pattern-in-java-example-tutorial/

案例源码下载:http://download.csdn.net/detail/ma20120607/8951193
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: