【设计模式】JAVA Design Patterns——Bytecode(字节码模式)

news2024/11/17 1:59:06

🔍目的


允许编码行为作为虚拟机的指令

🔍解释


真实世界例子

一个团队正在开发一款新的巫师对战游戏。巫师的行为需要经过精心的调整和上百次的游玩测试。每次当游戏设计师想改变巫师行为时都让程序员去修改代码这是不妥的,所以巫师行为以数据驱动的虚拟机方式实现。

通俗描述

字节码模式支持由数据而不是代码驱动的行为。

维基百科

指令集定义了可以执行的低级操作。一系列指令被编码为字节序列。虚拟机一次一条地执行这些指令,中间的值用栈处理。通过组合指令,可以定义复杂的高级行为。

程序示例

创建游戏对象 巫师

@AllArgsConstructor
@Setter
@Getter
@Slf4j
public class Wizard {

  private int health;
  private int agility;
  private int wisdom;
  private int numberOfPlayedSounds;
  private int numberOfSpawnedParticles;

  public void playSound() {
    LOGGER.info("Playing sound");
    numberOfPlayedSounds++;
  }

  public void spawnParticles() {
    LOGGER.info("Spawning particles");
    numberOfSpawnedParticles++;
  }
}

 展示虚拟机可用的指令。每个指令对于如何操作栈中的数据都有自己的语义。例如,增加指令,其取得栈顶的两个元素并把结果压入栈中。

@AllArgsConstructor
@Getter
public enum Instruction {

  LITERAL(1),         // e.g. "LITERAL 0", push 0 to stack
  SET_HEALTH(2),      // e.g. "SET_HEALTH", pop health and wizard number, call set health
  SET_WISDOM(3),      // e.g. "SET_WISDOM", pop wisdom and wizard number, call set wisdom
  SET_AGILITY(4),     // e.g. "SET_AGILITY", pop agility and wizard number, call set agility
  PLAY_SOUND(5),      // e.g. "PLAY_SOUND", pop value as wizard number, call play sound
  SPAWN_PARTICLES(6), // e.g. "SPAWN_PARTICLES", pop value as wizard number, call spawn particles
  GET_HEALTH(7),      // e.g. "GET_HEALTH", pop value as wizard number, push wizard's health
  GET_AGILITY(8),     // e.g. "GET_AGILITY", pop value as wizard number, push wizard's agility
  GET_WISDOM(9),      // e.g. "GET_WISDOM", pop value as wizard number, push wizard's wisdom
  ADD(10),            // e.g. "ADD", pop 2 values, push their sum
  DIVIDE(11);         // e.g. "DIVIDE", pop 2 values, push their division
  // ...
}

创建核心类  虚拟机 类 。 它将指令作为输入并执行它们以提供游戏对象行为。

@Getter
@Slf4j
public class VirtualMachine {

  private final Stack<Integer> stack = new Stack<>();

  private final Wizard[] wizards = new Wizard[2];

  public VirtualMachine() {
    wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),
        0, 0);
    wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),
        0, 0);
  }

  public VirtualMachine(Wizard wizard1, Wizard wizard2) {
    wizards[0] = wizard1;
    wizards[1] = wizard2;
  }

  public void execute(int[] bytecode) {
    for (var i = 0; i < bytecode.length; i++) {
      Instruction instruction = Instruction.getInstruction(bytecode[i]);
      switch (instruction) {
        case LITERAL:
          // Read the next byte from the bytecode.
          int value = bytecode[++i];
          // Push the next value to stack
          stack.push(value);
          break;
        case SET_AGILITY:
          var amount = stack.pop();
          var wizard = stack.pop();
          setAgility(wizard, amount);
          break;
        case SET_WISDOM:
          amount = stack.pop();
          wizard = stack.pop();
          setWisdom(wizard, amount);
          break;
        case SET_HEALTH:
          amount = stack.pop();
          wizard = stack.pop();
          setHealth(wizard, amount);
          break;
        case GET_HEALTH:
          wizard = stack.pop();
          stack.push(getHealth(wizard));
          break;
        case GET_AGILITY:
          wizard = stack.pop();
          stack.push(getAgility(wizard));
          break;
        case GET_WISDOM:
          wizard = stack.pop();
          stack.push(getWisdom(wizard));
          break;
        case ADD:
          var a = stack.pop();
          var b = stack.pop();
          stack.push(a + b);
          break;
        case DIVIDE:
          a = stack.pop();
          b = stack.pop();
          stack.push(b / a);
          break;
        case PLAY_SOUND:
          wizard = stack.pop();
          getWizards()[wizard].playSound();
          break;
        case SPAWN_PARTICLES:
          wizard = stack.pop();
          getWizards()[wizard].spawnParticles();
          break;
        default:
          throw new IllegalArgumentException("Invalid instruction value");
      }
      LOGGER.info("Executed " + instruction.name() + ", Stack contains " + getStack());
    }
  }

  public void setHealth(int wizard, int amount) {
    wizards[wizard].setHealth(amount);
  }
  // other setters ->
  // ...
}

展示虚拟机完整示例

 

  public static void main(String[] args) {

    var vm = new VirtualMachine(
        new Wizard(45, 7, 11, 0, 0),
        new Wizard(36, 18, 8, 0, 0));

    vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
    vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
    vm.execute(InstructionConverterUtil.convertToByteCode("GET_HEALTH"));
    vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
    vm.execute(InstructionConverterUtil.convertToByteCode("GET_AGILITY"));
    vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
    vm.execute(InstructionConverterUtil.convertToByteCode("GET_WISDOM"));
    vm.execute(InstructionConverterUtil.convertToByteCode("ADD"));
    vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 2"));
    vm.execute(InstructionConverterUtil.convertToByteCode("DIVIDE"));
    vm.execute(InstructionConverterUtil.convertToByteCode("ADD"));
    vm.execute(InstructionConverterUtil.convertToByteCode("SET_HEALTH"));
  }

控制台输出

 

16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0]
16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2]
16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9]
16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54]
16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains []

🔍类图


Bytecode class diagram 

🔍适用场景


当您需要定义很多行为并且游戏的实现语言不合适时,请使用字节码模式,因为:

  • 它的等级太低,使得编程变得乏味或容易出错。
  • 由于编译时间慢或其他工具问题,迭代它需要很长时间。
  • 它有太多的信任。 如果您想确保定义的行为不会破坏游戏,您需要将其与代码库的其余部分进行沙箱化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1693045.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安全态势管理的六大挑战:态势感知

德迅云安全鉴于如今的安全威胁不断变幻&#xff0c;企业对实施态势管理策略至关重要&#xff0c;可以让安全团队根据需要进行安全策略的动态调整。如果企业在研究构建态势感知管理&#xff0c;需要特别关注以下六个方面的挑战。 如果企业正在使用一个或多个平台&#xff0c;那么…

《计算机网络微课堂》课程概述

​ 课程介绍 本专栏主要是 B 站课程《计算机网络微课堂》的文字版&#xff0c;作者是湖南科技大学的老师。 B 站地址&#xff1a;https://www.bilibili.com/video/BV1c4411d7jb 该课程好评如潮&#xff0c;包含理论课&#xff0c;实验课&#xff0c;考研真题分析课&#xf…

GDB 调试器

GDB 功能 在程序启动之前指定一些可以影响程序行为的变量或条件。在某个指定的地方或条件下暂停程序&#xff0c;在程序停止时检查已经发生了什么。 调试信息与调试原理 一般要调试某个程序&#xff0c;为了能清晰地看到调试的每一行代码、调用的堆栈信息、变 量名和函数名等…

qt5core.dll怎么下载,qt5core.dll下载安装详细教程

不知道大家有没有遇到过qt5core.dll丢失这个问题&#xff1f;目前这个问题还是比较常见的&#xff0c;一般使用电脑比较多的的人&#xff0c;有很大几率遇到这种qt5core.dll丢失的问题。今天主要针对这个问题&#xff0c;来给大家讲解一下一键修复qt5core.dll的方法。 Qt5Core.…

图论(从数据结构的三要素出发)

文章目录 逻辑结构物理结构邻接矩阵定义性能分析性质存在的问题 邻接表定义性能分析存在的问题 十字链表(有向图)定义性能分析 邻接多重表(无向图)定义性能分析 数据的操作图的基本操作图的遍历广度优先遍历&#xff08;BFS&#xff09;算法思想和实现性能分析深度优先最小生成…

打开服务器远程桌面连接不上,可能的原因及相应的解决策略

在解决远程桌面连接不上服务器的问题时&#xff0c;我们首先需要从专业的角度对可能的原因进行深入分析&#xff0c;并据此提出针对性的解决方案。以下是一些可能的原因及相应的解决策略&#xff1a; 一、网络连接问题 远程桌面连接需要稳定的网络支持&#xff0c;如果网络连接…

【一步一步了解Java系列】:何为数组,何为引用类型

看到这句话的时候证明&#xff1a;此刻你我都在努力加油陌生人个人主页&#xff1a;Gu Gu Study专栏&#xff1a;一步一步了解Java 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 数组 数组是一推相同数据…

JavaSE--基础语法(第一期)

Java是一种优秀的程序设计语言&#xff0c;它具有令人赏心悦目的语法和易于理解的语义。不仅如此&#xff0c;Java还是一个有一系列计算机软件和规范形成的技术体系&#xff0c;这个技术体系提供了完整的用于软件开发和 跨平台部署的支持环境&#xff0c;并广泛应用于嵌入式系统…

特殊变量笔记

执行demo4.sh文件,输入输出参数itcast itheima的2个输入参数, 观察效果 特殊变量&#xff1a;$# 语法 $#含义 获取所有输入参数的个数 案例需求 在demo4.sh中输出输入参数个数 演示 编辑demo4.sh, 输出输入参数个数 执行demo4.sh传入参数itcast, itheima, 播仔 看效果…

上位机图像处理和嵌入式模块部署(mcu之串口控制gpio)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们陆续学习了gpio输入、输出&#xff0c;串口输入、输出。其实有了这两个接口&#xff0c;就可以做产品了。因为我们可以通过发送串口命令&a…

门禁-jenkins的构建状态同步到gitlab提交流水线

API接口文档 https://docs.gitlab.cn/jh/api/commits.html 配置pipline流水线 生成http请求代码&#xff1a; 使用HttpRequest插件生成 - sharelibs内容 //这是share libs里的 package devopsdef httpReq(reqType, reqUrl, reqBody, accessToken){def gitServer "…

人才测评的应用:人才选拔,岗位晋升,面试招聘测评

人才测评自诞生以来&#xff0c;就被广泛应用在各大方面&#xff0c;不仅是我们熟悉的招聘上&#xff0c;还有其他考核和晋升&#xff0c;都会需要用到人才测评。不知道怎么招聘&#xff1f;或者不懂得如何实现人才晋升&#xff1f;都可以参考人才测评&#xff0c;利用它帮我们…

Amesim基础篇-元件详解-H型膨胀阀四象限解析

一 膨胀阀简介 膨胀阀的主要功能是节流和调节过热度,库内膨胀阀包含节流管、H型膨胀阀、T型膨胀阀三种: 节流管:一根内径较小的管路,当制冷剂通过他时发生等等焓降压降温,具有成本低,内径不可变的特点,因此普遍在家用空调中使用,在汽车空调上使用较少。当我们建模过程…

深入理解CPU缓存一致性

存储体系结构 速度快的存储硬件成本高、容量小&#xff0c;速度慢的成本低、容量大。为了权衡成本和速度&#xff0c;计算机存储分了很多层次&#xff0c;有寄存器、L1 cache、L2 cache、L3 cache、主存&#xff08;内存&#xff09;和硬盘等。 根据程序的空间局部性和时间局…

Java开发大厂面试第22讲:Redis 是如何保证系统高可用的?它的实现方式有哪些?

高可用是通过设计&#xff0c;减少系统不能提供服务的时间&#xff0c;是分布式系统的基础也是保障系统可靠性的重要手段。而 Redis 作为一款普及率最高的内存型中间件&#xff0c;它的高可用技术也非常的成熟。 我们今天分享的面试题是&#xff0c;Redis 是如何保证系统高可用…

Mac上安装OpenLDAP服务器详细教程(Homebrew安装和自带的ldap)

目录 前言 一、安装 Homebrew&#xff08;如果尚未安装&#xff09; 二、使用 Homebrew 安装 OpenLDAP 三、配置 OpenLDAP 步骤一&#xff1a;更新PATH和环境变量 步骤二&#xff1a;配置slapd.conf 步骤三&#xff1a;初始化和启动 OpenLDAP 服务 1.创建数据库目录 2…

你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

目录 一、onMounted的前世今生 1.1、onMounted是什么 1.2、onMounted在vue2中的前身 1.2.1、vue2中的onMounted 1.2.2、Vue2与Vue3的onMounted对比 1.3、vue3中onMounted的用法 1.3.1、基础用法 1.3.2、顺序执行异步操作 1.3.3、并行执行多个异步操作 1.3.4、执行一次…

非等值连接、等值连接、自然连接

目录 一、笛卡尔积 二、三种连接的关系 三、非等值连接 四、等值连接 五、自然连接 一、笛卡尔积 要理解非等值连接、等值连接、自然连接首先要理解笛卡尔积。 学过《离散数学》的应该很熟悉笛卡尔积。 简单来说&#xff0c;就是有两个集合&#xff0c;其中一个集合中的元…

【华三包过】2024年/华三H3C/云计算GB0-713

H3CNE-cloud-云计算-713 想转行 想继续深入 题库覆盖百分百&#xff0c;题库有新版106道新版113道旧版88道 H3C认证云计算工程师&#xff08;H3C Certified Network Engineer for Cloud&#xff0c;简称H3CNE-Cloud&#xff09; 认证定位于全面掌握虚拟化技术原理及相关产品/…

部门来了个测试开发,听说是00后,上来一顿操作给我看蒙了...

公司新来了个同事&#xff0c;听说大学是学的广告专业&#xff0c;因为喜欢IT行业就找了个培训班&#xff0c;后来在一家小公司实习半年&#xff0c;现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍&#xff0c;服务器缩减一半&#xff0c;性能反而提升4倍&#xff01…