设计模式之十七:访问者模式

在数据基础类里面有一个方法接受访问者,将自身引用传入访问者

利用“双重分派”分派到实例内部,弥补Java多态中的方法重载时静态的,这一问题

Java的方法重载是静态的:
方法重载时,若参数有父类的,也有子类的,则按声明的类型调用,而不是实例的真正类型。
eg. 对于重载的方法test(Father f)和test(Son s),若Father f = new Son();,调用test(f)则会以Father的类型传入。
所以,用父类的引用无法代表子类的实例。但是this指针的类型是本类。

事例

需求:对苹果、桔子、香蕉进行清仓甩卖

数据结构如图:

在这里插入图片描述

接口及其实现类代码如下:

public interface Fruit {
    void accept(Visit visit);
}

public class Apple implements Fruit {
    int price = 100;

    @Override
    public void accept(Visit visit) {
        visit.sell(this);
    }
}

public class Orange implements Fruit {
    int price = 80;

    @Override
    public void accept(Visit visit) {
        visit.sell(this);
    }
}

public class Banana implements Fruit {
    int price = 20;

    @Override
    public void accept(Visit visit) {
        visit.sell(this);
    }
}

访问者类。通过方法重载,根据参数类型不同而执行不同的逻辑

public class Visit {

    /*
    方法的重载
     */
    public void sell(Apple apple) {
        // 卖苹果
    }

    public void sell(Orange orange) {
        // 卖桔子
    }

    public void sell(Banana banana) {
        // 卖香蕉
    }

	public void sell(Fruit fruit) {
        // 其他水果。缺省情况
    }
}

测试:客户持有数据集合和访问类。

public class VisitClient {

    private List<Fruit> mList = new ArrayList<>();
    private Visit mVisit = new Visit();

	// 添加要甩卖的水果
    {
        mList.add(new Apple());
        mList.add(new Orange());
        mList.add(new Banana());
    }

    // 清仓甩卖
    private void clearOut() {
        for (Fruit fruit : mList) {
            fruit.accept(mVisit);
        }
    }
}

总结

适用场景

  • 集合中有不同类型的对象,要识别它们真实类型
  • 数据结构对应的类固定不变时
  • 对数据类增加新操作,又不想修改数据类

优点

  • 避免污染数据类。由访问类判断真实类型并转发业务
  • 符合单一职责
  • 扩展性高
  • 灵活性高

缺点

  • 对访问者公布细节,违反了迪米特原则
  • 违反了依赖倒置原则,依赖了具体类,没有依赖抽象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈哈利波特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值