java 访问者模式_java中的访问者模式 – 例子辅导

本文介绍了一种行为设计模式——访问者模式,该模式允许在不修改对象结构的情况下为一组对象添加新的行为。通过购物车计算商品总价的例子,展示了如何利用访问者模式实现不同商品类型的计费逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接 作者:Pankaj Kumar 译者:f0tlo <1357654289@qq.com>

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

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

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

ItemElement.java

package com.journaldev.design.visitor;

public interface ItemElement {

public int accept(ShoppingCartVisitor visitor);

}

注意,accept方法接受访问者作为参数。当然这儿还有其他的一些方法来指定详细的商品,但为了简化,此处没用过多的考虑细节,只关注访问者模式。

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

Book.java

package com.journaldev.design.visitor;

public class Book implements ItemElement {

private int price;

private String isbnNumber;

public Book(int cost, String isbn){

this.price=cost;

this.isbnNumber=isbn;

}

public int getPrice() {

return price;

}

public String getIsbnNumber() {

return isbnNumber;

}

@Override

public int accept(ShoppingCartVisitor visitor) {

return visitor.visit(this);

}

}

Fruit.java

package com.journaldev.design.visitor;

public class Fruit implements ItemElement {

private int pricePerKg;

private int weight;

private String name;

public Fruit(int priceKg, int wt, String nm){

this.pricePerKg=priceKg;

this.weight=wt;

this.name = nm;

}

public int getPricePerKg() {

return pricePerKg;

}

public int getWeight() {

return weight;

}

public String getName(){

return this.name;

}

@Override

public int accept(ShoppingCartVisitor visitor) {

return visitor.visit(this);

}

}

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

此处针对不同类型的商品所使用的visit()方法将会在访问者接口的实体类中被实现。

ShoppingCartVisitor.java

package com.journaldev.design.visitor;

public interface ShoppingCartVisitor {

int visit(Book book);

int visit(Fruit fruit);

}

现在将实现访问者接口以及每种商品自己计算自己费用的逻辑。

ShoppingCartVisitorImpl.java

package com.journaldev.design.visitor;

public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {

@Override

public int visit(Book book) {

int cost=0;

//apply 5$ discount if book price is greater than 50

if(book.getPrice() > 50){

cost = book.getPrice()-5;

}else cost = book.getPrice();

System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);

return cost;

}

@Override

public int visit(Fruit fruit) {

int cost = fruit.getPricePerKg()*fruit.getWeight();

System.out.println(fruit.getName() + " cost = "+cost);

return cost;

}

}

现在看一看在程序中如何使用它。

ShoppingCartClient.java

package com.journaldev.design.visitor;

public class ShoppingCartClient {

public static void main(String[] args) {

ItemElement[] items = new ItemElement[]{new Book(20, "1234"),new Book(100, "5678"),

new Fruit(10, 2, "Banana"), new Fruit(5, 5, "Apple")};

int total = calculatePrice(items);

System.out.println("Total Cost = "+total);

}

private static int calculatePrice(ItemElement[] items) {

ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();

int sum=0;

for(ItemElement item : items){

sum = sum + item.accept(visitor);

}

return sum;

}

}

当运行上述程序是,我们得到如下输出。

Book ISBN::1234 cost =20

Book ISBN::5678 cost =95

Banana cost = 20

Apple cost = 25

Total Cost = 160

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

访问者模式用例图

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

visitor-pattern.png

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

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

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

d0c1501a6d8bb921cf36400dc89de69f.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值