首页 > 其他分享 >访问者模式

访问者模式

时间:2023-02-18 23:34:18浏览次数:32  
标签:getMoney Money 分派 模式 money new public 访问者

  • 解耦数据结构和数据
  • 三种角色
    • 访问者IPeople:对数据结构的访问
    • 被访问者IMoney:被访问的数据结构
    • 容器BankContainer:用于装载数据结构,提供方法接受访问者访问所有的数据结构
  • UML类图
/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:23
 * @Description:抽象接口钱
 */
public interface IMoney {

    /**
     * 接受人来取钱
     *
     * @param people 中国人、美国人、等等.....
     */
    void accept(IPeople people);

    /**
     * 取钱
     *
     * @return int
     */
    int getMoney();
}
/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:30
 * @Description:美元, 实现了抽象接口 {@link IMoney} 接受美人来取美元
 */
public class DollarMoney implements IMoney {
    @Override
    public void accept(IPeople people) {
        System.out.println("DollarMoney取钱");
        people.visit(this);
    }

    @Override
    public int getMoney() {
        return 10;
    }
}
/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:26
 * @Description: 人民币, 实现了抽象接口 {@link IMoney} 接受人来取人民币
 */
public class RmbMoney implements IMoney {
    @Override
    public void accept(IPeople people) {
        System.out.println("RmbMoney取钱");
        people.visit(this);
    }

    @Override
    public int getMoney() {
        return 20;
    }
}

/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:24
 * @Description: 人, 其子类分为中国人、美国人
 */
public interface IPeople {

    /**
     * 人去取钱
     *
     * @param money 钱
     */
    void visit(IMoney money);
}

/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:34
 * @Description: 中国人, 实现接口{@link IPeople}, 完成对人民币的访问
 */
public class Chinese implements IPeople {
    @Override
    public void visit(IMoney money) {
        System.out.println("我是中国人, 我来取钱了, 取了" + money.getMoney() + "元");
    }
}

/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:34
 * @Description: 美国人, 实现接口{@link IPeople}, 完成对美元的访问
 */
public class American implements IPeople {
    @Override
    public void visit(IMoney money) {
        System.out.println("我是美国人, 我来取钱了, 取了" + money.getMoney() + "元");
    }
}

/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:44
 * @Description: 银行存储钱的容器
 */
public class BankContainer {

    private List<IMoney> list;

    public BankContainer() {
        this.init();
    }

    private void init(){
        list = new CopyOnWriteArrayList<>();
        list.add(new RmbMoney());
        list.add(new DollarMoney());
    }

    public void getMoney(IPeople people){
        for (IMoney money : this.list) {
            money.accept(people);
        }
    }
}

/**
 * @Author: lxpStu
 * @Date: 2023/02/18/10:48
 * @Description:
 */
public class ClientVisitor {

    public static void main(String[] args) {
        BankContainer container = new BankContainer();
        System.out.println("===========中国人取钱===========");
        container.getMoney(new Chinese());
        System.out.println("===========美国人取钱===========");
        container.getMoney(new American());
    }
}
  • 输出结果
  • 编译期和运行期
    • 编译期:指程序文件编译为汇编程序,再由汇编程序编译为机器语言的过程, 在Java中编译期指程序被编译为.class文件
    • 运行期:指程序真正执行的时期.
  • 分派
    • 分派是指根据对象的类型进行方法的选择, 在Java中对象的类型在编译期和运行期有可能是不同的, 所谓编译看左, 运行看右.
    • 如 Money money = new Rmb(); 变量 money在编译期类型是 Money, 在运行期实际的类型是Rmb, 从而引出了分派的两种类型.
  • 分派的分类
    • 静态分派:也叫编译期分派,根据编译期的变量定义的类型决定程序执行的方法是哪个, 比如重载就是静态分派, Java中重载方法的参数类型不同、参数个数可能也不同, 所以静态分派说Java是静态多分派的.
    • 动态分派:也叫运行期分派,根据运行期的变量实际的类型决定程序执行的方法是哪个, 比如重写就是动态态分派, Java中对象的实际类型只能对应一个重写方法, 所以说Java是动态单分派的.
  • 访问者模式的伪动态双分派
    • Java只支持动态单分派, 想要支持动态双分派必须基于代码层面的设计模式解决, 所以说访问者模式是伪动态双分派的,在ClientVisitor中第一次根据人的类型即【new BankContainer().getMoney(new Chinese())和 new BankContainer().getMoney(new American())】完成了第一次动态分派.将人的实际类型传递给了RmbMoney和DollarMoney的accept()在IMoney的子类(如RmbMoney)的accept()中又调用人的visit(this), 并将自己的this对象传入, 我们知道this对象代表本类的实例, 所以完成了第二次动态分派, 即调用了某人的visit()方法
  • 分派的code演示
public class Money {
}
class Rmb extends Money {}
class Dollar extends Money {}
class Bank{
    public void getMoney(Money money){
        System.out.println("Money");
    }
    public void getMoney(Rmb rmb){
        System.out.println("RMB");
    }
    public void getMoney(Dollar dollar){
        System.out.println("Dollar");
    }
}
class DispatchClient {
    public static void main(String[] args) {
        Money money = new Money();
        Money rmb = new Rmb();
        Money dollar = new Dollar();
        Bank bank = new Bank();
        System.out.println("=====静态分派=====");
        bank.getMoney(money);// Money
        bank.getMoney(rmb);// Money
        bank.getMoney(dollar);// Money
        System.out.println("=====动态分派=====");
        bank.getMoney(new Money());// Money
        bank.getMoney(new Rmb());//RMB
        bank.getMoney(new Dollar());//Dollar
    }
}

标签:getMoney,Money,分派,模式,money,new,public,访问者
From: https://www.cnblogs.com/lxpStu/p/17133944.html

相关文章

  • Python实现单例模式
    Python实现单例模式有两种方法:一种是通过静态变量方法实现单例模式;另一种是通过装饰器实现单例模式。具体实现代码如下:#方法一:静态变量方法实现单例模式。#1.构造方法私有......
  • 微软出品自动化神器【Playwright+Java】系列(九)多线程、重定向、弹出新窗口、截图、新
    写在前面关于Playwright系列的文章,真的很久没有写了,今天一个不小心官方API部分过完了,下面将为大家逐一演示,感兴趣的同学可以自行动手练习。API部分多线程直白点说就是......
  • 嵌入式ARM设计编程(三) 处理器工作模式
    文章和代码已归档至【Github仓库:​​hardware-tutorial​​】,需要的朋友们自取。或者关注公众号【AIShareLab】,回复嵌入式也可获取。一、实验目的(1)通过实验掌握学会使用m......
  • ZMQ之脱机可靠性--巨人模式
      当你意识到管家模式是一种非常可靠的消息代理时,你可能会想要使用磁盘做一下消息中转,从而进一步提升可靠性。这种方式虽然在很多企业级消息系统中应用,但我还是有些反对的......
  • WPF中MVVM模式下loaded无法触发问题
    经过实践检测,当时View上设置了Window.SizeToContent="WidthAndHeight"时候<i:Interaction.Triggers><i:EventTriggerEventName="Loaded"><i:Invoke......
  • macOS Ventura13 的专注模式,帮你轻松专注当下
    无论你在工作、休闲,还是准备与家人共度美好时光,macOSVentura的专注模式过滤条件都能帮你轻松专注当下,让各种App根据你启用的专注模式定制你看到的内容和获取的通知。
......
  • 软件测试的七类驱动测试模式
    在进行软件测试时,总要有一个出发点吧?从哪里开始分析?测试设计是基于什么?简单地说,什么是驱动测试工作?这是一个基本问题,基于自己多年对软件工程、产品质量和测试等的......
  • 设计模式
    说一说设计模式的六大原则单一职责原则一个类,应当只有一个引起它变化的原因;即一个类应该只有一个原则。就一个类而言,应该只专注于做一件事和仅有一个引起变化的原因,着就......
  • 设计模式(八)----创建型模式之建造者模式与工厂模式区别
    1、工厂方法模式VS建造者模式工厂方法模式注重的是整体对象的创建方式;而建造者模式注重的是部件构建的过程,意在通过一步一步地精确构造创建出一个复杂的对象。我们举个简......
  • 设计模式(九)----结构型模式之代理模式
    一、结构型模式结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制或者实现机制来组织接口和类,后者釆用组合或......