mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-14 12:58:37 +00:00
docs: collecting parameter docs + formatting
This commit is contained in:
+34
-17
@@ -3,7 +3,7 @@ title: Bytecode
|
||||
category: Behavioral
|
||||
language: en
|
||||
tag:
|
||||
- Game programming
|
||||
- Game programming
|
||||
---
|
||||
|
||||
## Intent
|
||||
@@ -14,22 +14,28 @@ Allows encoding behavior as instructions for a virtual machine.
|
||||
|
||||
Real world example
|
||||
|
||||
> A team is working on a new game where wizards battle against each other. The wizard behavior needs to be carefully adjusted and iterated hundreds of times through playtesting. It's not optimal to ask the programmer to make changes each time the game designer wants to vary the behavior, so the wizard behavior is implemented as a data-driven virtual machine.
|
||||
> A team is working on a new game where wizards battle against each other. The wizard behavior needs to be carefully
|
||||
> adjusted and iterated hundreds of times through playtesting. It's not optimal to ask the programmer to make changes each
|
||||
> time the game designer wants to vary the behavior, so the wizard behavior is implemented as a data-driven virtual
|
||||
> machine.
|
||||
|
||||
In plain words
|
||||
|
||||
> Bytecode pattern enables behavior driven by data instead of code.
|
||||
|
||||
[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) documentation
|
||||
[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) documentation
|
||||
states:
|
||||
|
||||
> An instruction set defines the low-level operations that can be performed. A series of instructions is encoded as a sequence of bytes. A virtual machine executes these instructions one at a time, using a stack for intermediate values. By combining instructions, complex high-level behavior can be defined.
|
||||
> An instruction set defines the low-level operations that can be performed. A series of instructions is encoded as a
|
||||
> sequence of bytes. A virtual machine executes these instructions one at a time, using a stack for intermediate values.
|
||||
> By combining instructions, complex high-level behavior can be defined.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
One of the most important game objects is the `Wizard` class.
|
||||
|
||||
```java
|
||||
|
||||
@AllArgsConstructor
|
||||
@Setter
|
||||
@Getter
|
||||
@@ -54,9 +60,12 @@ public class Wizard {
|
||||
}
|
||||
```
|
||||
|
||||
Next, we show the available instructions for our virtual machine. Each of the instructions has its own semantics on how it operates with the stack data. For example, the ADD instruction takes the top two items from the stack, adds them together and pushes the result to the stack.
|
||||
Next, we show the available instructions for our virtual machine. Each of the instructions has its own semantics on how
|
||||
it operates with the stack data. For example, the ADD instruction takes the top two items from the stack, adds them
|
||||
together and pushes the result to the stack.
|
||||
|
||||
```java
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum Instruction {
|
||||
@@ -76,9 +85,11 @@ public enum Instruction {
|
||||
}
|
||||
```
|
||||
|
||||
At the heart of our example is the `VirtualMachine` class. It takes instructions as input and executes them to provide the game object behavior.
|
||||
At the heart of our example is the `VirtualMachine` class. It takes instructions as input and executes them to provide
|
||||
the game object behavior.
|
||||
|
||||
```java
|
||||
|
||||
@Getter
|
||||
@Slf4j
|
||||
public class VirtualMachine {
|
||||
@@ -172,11 +183,11 @@ public class VirtualMachine {
|
||||
Now we can show the full example utilizing the virtual machine.
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[]args){
|
||||
|
||||
var vm = new VirtualMachine(
|
||||
new Wizard(45, 7, 11, 0, 0),
|
||||
new Wizard(36, 18, 8, 0, 0));
|
||||
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"));
|
||||
@@ -190,7 +201,7 @@ Now we can show the full example utilizing the virtual machine.
|
||||
vm.execute(InstructionConverterUtil.convertToByteCode("DIVIDE"));
|
||||
vm.execute(InstructionConverterUtil.convertToByteCode("ADD"));
|
||||
vm.execute(InstructionConverterUtil.convertToByteCode("SET_HEALTH"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here is the console output.
|
||||
@@ -216,11 +227,13 @@ Here is the console output.
|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Bytecode pattern when you have a lot of behavior you need to define and your game’s implementation language isn’t a good fit because:
|
||||
Use the Bytecode pattern when you have a lot of behavior you need to define and your game’s implementation language
|
||||
isn’t a good fit because:
|
||||
|
||||
* It’s too low-level, making it tedious or error-prone to program in.
|
||||
* Iterating on it takes too long due to slow compile times or other tooling issues.
|
||||
* It has too much trust. If you want to ensure the behavior being defined can’t break the game, you need to sandbox it from the rest of the codebase.
|
||||
* It has too much trust. If you want to ensure the behavior being defined can’t break the game, you need to sandbox it
|
||||
from the rest of the codebase.
|
||||
|
||||
## Known Uses
|
||||
|
||||
@@ -238,14 +251,18 @@ Benefits:
|
||||
|
||||
Trade-offs:
|
||||
|
||||
* Overhead: Running bytecode typically involves more overhead than running native code, potentially affecting performance.
|
||||
* Overhead: Running bytecode typically involves more overhead than running native code, potentially affecting
|
||||
performance.
|
||||
* Complexity: Implementing and maintaining a VM adds complexity to the system.
|
||||
|
||||
## Related patterns
|
||||
|
||||
* [Interpreter](https://java-design-patterns.com/patterns/interpreter/) is often used within the implementation of VMs to interpret bytecode instructions
|
||||
* [Command](https://java-design-patterns.com/patterns/command/): Bytecode instructions can be seen as commands executed by the VM.
|
||||
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): VMs may use factory methods to instantiate operations or instructions defined in the bytecode.
|
||||
* [Interpreter](https://java-design-patterns.com/patterns/interpreter/) is often used within the implementation of VMs
|
||||
to interpret bytecode instructions
|
||||
* [Command](https://java-design-patterns.com/patterns/command/): Bytecode instructions can be seen as commands executed
|
||||
by the VM.
|
||||
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): VMs may use factory methods to
|
||||
instantiate operations or instructions defined in the bytecode.
|
||||
|
||||
## Credits
|
||||
|
||||
|
||||
Reference in New Issue
Block a user