(十九)访问者模式

(十九)访问者模式_第1张图片
image.png

水果店中有各种水果的库存积累,需要大甩卖,可以利用java的多态实现


(十九)访问者模式_第2张图片
image.png

现在有水果接口Fruit,访问者Visit

public class Visit {
    //苹果计价
    public int sell(Apple apple){
        System.out.println("apple's price: ¥50");
        return 50;
    }
    //桔子计价
    public int sell(Orange orange){
        System.out.println("orange's price: ¥20");
        return 20;
    }
    //香蕉计价
    public int sell(Banana banana){
        System.out.println("banana's price: ¥30");
        return 30;
    }
    //其它水果计价
    public int sell(Fruit fruit){
        System.out.println("other price: ¥10");
        return 10;
    }
}
public class VisitClient {
    private static Visit visit = new Visit();
    private static List list = new ArrayList<>();//库存

    static {
        list.add(StaticFactory.getFruitApple());
        list.add(StaticFactory.getFruitOrange());
        list.add(StaticFactory.getFruitBanana());
        list.add(StaticFactory.getFruitApple());
        list.add(StaticFactory.getFruitOrange());
    }

    //统计库存
    private static int price() {
        int total = 0;
        for (Fruit fruit : list) {
            total += visit.sell(fruit);
//            total += fruit.accept(visit);
        }
        System.out.println("总价值:" + total);
        return total;
    }
    public static void main(String[] args) {
        price();
    }
}

虽然visit的sell方法是多态的,但是由于java的多态方法重载是静态的,无法动态识别真实对象的类型,所以在for循环中,sell的方法的参数都被认为是Fruit类型,结果都调用了sell(Fruit fruit)方法了
那么如何优雅地实现动态重载呢
虽然多态参数无法动态识别真实对象,但是如果在真实对象的内部使用this指针可以正确识别真实对象类型

public class Apple implements Fruit {
    private int price = 100;
    public Apple(){

    }
    public Apple(int price){
        this.price = price;
    }
    @Override
    public int price() {
        return price;
    }
    @Override
    public void draw() {
        System.out.print("苹果红富士");
    }
    public int accept(Visit visit){
        return visit.sell(this);//指针可以传递真实类型
    }
    public static void main(String[] args) {
        Visit visit = new Visit();
        new Apple().accept(visit);
    }
}
public interface Fruit {
    int price();
    void draw();
    int accept(Visit visit);
}

访问者模式

(十九)访问者模式_第3张图片
image.png

(十九)访问者模式_第4张图片
image.png

本来是通过Visit的多态方法直接实现功能,现在为了动态重载参数类型,使用this关键字在真实对象内部识别真实对象类型

public class VisitClient {
    private static Visit visit = new Visit();
    private static List list = new ArrayList<>();//库存
    static {
        list.add(StaticFactory.getFruitApple());
        list.add(StaticFactory.getFruitOrange());
        list.add(StaticFactory.getFruitBanana());
        list.add(StaticFactory.getFruitApple());
        list.add(StaticFactory.getFruitOrange());
    }
    //统计库存
    private static int price() {
        int total = 0;
        for (Fruit fruit : list) {
            //total += visit.sell(fruit);
            total += fruit.accept(visit);//在真实内部调用visit功能识别真实对象类型
        }
        System.out.println("总价值:" + total);
        return total;
    }
    public static void main(String[] args) {
        price();
    }
}

总结

  • 访问者模式是利用双重分派机制来弥补java多态中方法重载是静态化的不足,实现优雅变成的目的

你可能感兴趣的:((十九)访问者模式)