Design Pattern(5)-Visitor Pattern

典型应用场景

一个集合容器,里面有一系列元素,但是不同的元素类型不太一样,例如A,B,C,D,但是不同的元素肯定继承自同一个父类或者实现同一个接口,不妨设为Element,毕竟这样才能在同一个集合数据结构里面。现在你想要遍历这个集合,譬如你想得到每个元素的价格,然后求个总价,自然想到的方法是为Element加一个getPrice()方法,然后每个子类都实现这个方法,每个子类可以根据自己的情况选择不同的实现。最终达到求总价的目的。

存在问题

上面解决了求总价的问题,但是如果你哪天又想要求总数量呢?获取每个元素的重量以求得最大的重量呢?用上面的方法,必须为Element再加一个getWeight()亦或是getNum()方法。这必须修改类内代码,对于一些坚持OCP原则的人来说,这不能忍。所以它们想出了Visitor Pattern。

类图

这里写图片描述

实例代码

本例是一个元素集合,集合里面有蔬菜、书,现在要求求总价,所以有了个PriceVisitor,如果你还要得到重量,也可以添加WeightVisitor. 有几个操作就是几个Visitor。不需要修改原有代码,只需要添加具体Visitor类。

Element:

public abstract class Element {
    abstract double accept(Visitor visitor);
}

Book:

public class Book extends Element{
    private String ISBN;

    public Book(String ISBN) {
        this.ISBN = ISBN;
    }

    public String getISBN() {
        return ISBN;
    }

    @Override
    double accept(Visitor visitor) {
        return visitor.visitBook(this);
    }
}

Fruit:

public class Fruit extends Element {
    private double num;
    private double price;

    public Fruit(double num,double price) {
        this.num = num;
        this.price=price;
    }

    public double getPrice() {
        return price;
    }

    public double getNum() {
        return num;
    }

    @Override
    double accept(Visitor visitor) {
        return visitor.visitFruit(this);
    }
}

Visitor:

public interface Visitor {
    double visitFruit(Fruit fruit);
    double visitBook(Book book);
}

PriceVisitor:

public class PriceVisitor implements Visitor {
    @Override
    public double visitFruit(Fruit fruit) {
        return fruit.getPrice()*fruit.getNum();
    }

    @Override
    public double visitBook(Book book) {
        String ISBN=book.getISBN();
        if(ISBN.charAt(0)=='a')
            return 100;
        else
            return 200;
    }
}

Client:

public class Client {
    public static void main(String[] args){
        List<Element> list=new ArrayList<>();
        list.add(new Book("a9148210"));
        list.add(new Fruit(20,2));
        list.add(new Book("b2213"));
        list.add(new Fruit(10,3));

        Visitor visitor=new PriceVisitor();
        double sum=0;
        for(Element element:list){
            sum+=element.accept(visitor);
        }
        System.out.print(sum);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值