将行为拆成请求与执行两个区块,请求的部分独自封装成物件,执行的部分则交由专门负责执行的物件。
负责执行的物件除了储存等待执行的请求,还可以在执行前取消特定请求。
想像一个情况,使用者可以很简单地说出要执行的行为,负责执行的程序可以迅速反应,转换到设计上,单个要执行的行为,经常包装成物件,物件内有执行的细节。
现在情况改变,有许多的行为可以执行,那要建立相同数量的物件,数量越多,越不容易管理,因为分散各地。
此外,如果需要一个历史清单追踪要执行的行为,以及取消特定行为呢?
单纯的「传球、接球」模式无法做到。
为了实践这两个新需求,可以将执行的细节封装在特定物件内,原本的包装行为的物件简化成呼叫特定物件内的对应方法。
实践的作法是:
以下范例以「模拟世纪帝国二的基本操作」为核心制作。
单位物件:Villager
、Paladin
、House
、Castle
public class Villager {
private int healthPoints;
private Headquarters headquarters;
public Villager(Headquarters headquarters) {
healthPoints = 25;
this.headquarters = headquarters;
}
public void gotDamage(int damagePoints) {
healthPoints -= damagePoints;
if (healthPoints < 0) {
headquarters.removeVillager();
}
}
}
public class Paladin {
private int healthPoints;
private Headquarters headquarters;
public Paladin(Headquarters headquarters) {
healthPoints = 160;
this.headquarters = headquarters;
}
public void gotDamage(int damagePoints) {
healthPoints -= damagePoints;
if (healthPoints < 0) {
headquarters.removePaladin();
}
}
}
public class House {
private int healthPoints;
private Headquarters headquarters;
public House(Headquarters headquarters) {
healthPoints = 550;
this.headquarters = headquarters;
}
public void gotDamage(int damagePoints) {
healthPoints -= damagePoints;
if (healthPoints < 0) {
headquarters.removeHouse();
}
}
}
public class Castle {
private int healthPoints;
private Headquarters headquarters;
public Castle(Headquarters headquarters) {
healthPoints = 4800;
this.headquarters = headquarters;
}
public void gotDamage(int damagePoints) {
healthPoints -= damagePoints;
if (healthPoints < 0) {
headquarters.removeCastle();
}
}
}
特定物件(Receiver)
public class Headquarters {
private int woodCounts;
private int foodCounts;
private int goldCounts;
private int stoneCounts;
private ArrayList<Villager> villagerList = new ArrayList<>();
private ArrayList<Paladin> paladinList = new ArrayList<>();
private ArrayList<House> houseList = new ArrayList<>();
private ArrayList<Castle> castleList = new ArrayList<>();
public Headquarters() {
woodCounts = 100;
foodCounts = 100;
goldCounts = 50;
stoneCounts = 50;
}
public void createVillager() {
if (foodCounts < 50) {
System.out.println("食物不足,无法生产村民\n");
} else {
System.out.println("食物充足,已生产村民\n");
villagerList.add(new Villager(this));
foodCounts -= 50;
}
}
public void removeVillager() {
if (villagerList.isEmpty()) {
System.out.println("没有村民可以删除");
} else {
villagerList.remove(0);
System.out.println("村民已删除");
}
}
public void createPaladin() {
if (foodCounts < 60) {
System.out.println("食物不足,无法生产游侠\n");
} else if (goldCounts < 75) {
System.out.println("黄金不足,无法生产游侠\n");
} else {
System.out.println("食物充足,已生产游侠\n");
paladinList.add(new Paladin(this));
foodCounts -= 60;
goldCounts -= 75;
}
}
public void removePaladin() {
if (paladinList.isEmpty()) {
System.out.println("没有游侠可以删除");
} else {
paladinList.remove(0);
System.out.println("游侠已删除");
}
}
public void createHouse() {
if (woodCounts < 25) {
System.out.println("木头不足,无法建造居住房舍\n");
} else {
System.out.println("木头充足,已建造居住房舍\n");
houseList.add(new House(this));
woodCounts -= 25;
}
}
public void removeHouse() {
if (houseList.isEmpty()) {
System.out.println("没有居住房舍可以删除");
} else {
houseList.remove(0);
System.out.println("居住房舍已删除");
}
}
public void createCastle() {
if (stoneCounts < 650) {
System.out.println("石头不足,无法建造城堡\n");
} else {
System.out.println("石头充足,已建造城堡\n");
castleList.add(new Castle(this));
stoneCounts -= 600;
}
}
public void removeCastle() {
if (castleList.isEmpty()) {
System.out.println("没有城堡可以删除");
} else {
castleList.remove(0);
System.out.println("城堡已删除");
}
}
public void gatherWood() {
if (villagerList.isEmpty()) {
System.out.println("没有村民可用\n");
} else {
System.out.println("村民数量足够,开始砍树\n");
woodCounts += 100;
}
}
public void gatherFood() {
if (villagerList.isEmpty()) {
System.out.println("没有村民可用\n");
} else {
System.out.println("村民数量足够,开始采集食物\n");
foodCounts += 100;
}
}
public void gatherGold() {
if (villagerList.isEmpty()) {
System.out.println("没有村民可用\n");
} else {
System.out.println("村民数量足够,开始挖金矿\n");
goldCounts += 100;
}
}
public void gatherStone() {
if (villagerList.isEmpty()) {
System.out.println("没有村民可用\n");
} else {
System.out.println("村民数量足够,开始挖石矿\n");
stoneCounts += 100;
}
}
public void showResources() {
System.out.println("---当前资源---");
System.out.println("木头: " + woodCounts);
System.out.println("食物: " + foodCounts);
System.out.println("黄金: " + goldCounts);
System.out.println("石头: " + stoneCounts);
System.out.println("---当前建筑数量---");
System.out.println("居住房舍: " + houseList.size());
System.out.println("城堡: " + castleList.size());
System.out.println("---当前单位数量---");
System.out.println("村民: " + villagerList.size());
System.out.println("游侠: " + paladinList.size());
System.out.println("---完毕---\n");
}
}
行为的虚拟层亲代:Command
public abstract class Command {
protected Headquarters headquarters;
protected Command(Headquarters headquarters) {
this.headquarters = headquarters;
}
public abstract void executeCommand();
public abstract String getName();
}
行为子代:CreateVillagerCommand
、RemoveVillagerCommand
、CreatePaladinCommand
、RemovePaladinCommand
、CreateHouseCommand
、RemoveHouseCommand
、CreateCastleCommand
、RemoveCastleCommand
、GatherFoodCommand
、GatherGoldCommand
、GatherStoneCommand
、GatherWoodCommand
、ShowResourcesCommand
(Command 物件)
public class CreateVillagerCommand extends Command {
private String name = "生产村民";
public CreateVillagerCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.createVillager();
}
@Override
public String getName() {
return name;
}
}
public class RemoveVillagerCommand extends Command {
private String name = "删除村民";
public RemoveVillagerCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.removeVillager();
}
@Override
public String getName() {
return name;
}
}
public class CreatePaladinCommand extends Command {
private String name = "生产游侠";
public CreatePaladinCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.createPaladin();
}
@Override
public String getName() {
return name;
}
}
public class RemovePaladinCommand extends Command {
private String name = "删除游侠";
public RemovePaladinCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.removePaladin();
}
@Override
public String getName() {
return name;
}
}
public class CreateHouseCommand extends Command {
private String name = "建造居住房舍";
public CreateHouseCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.createHouse();
}
@Override
public String getName() {
return name;
}
}
public class RemoveHouseCommand extends Command {
private String name = "删除居住房舍";
public RemoveHouseCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.removeHouse();
}
@Override
public String getName() {
return name;
}
}
public class CreateCastleCommand extends Command {
private String name = "建造城堡";
public CreateCastleCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.createCastle();
}
@Override
public String getName() {
return name;
}
}
public class RemoveCastleCommand extends Command {
private String name = "删除城堡";
public RemoveCastleCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.removeCastle();
}
@Override
public String getName() {
return name;
}
}
public class GatherFoodCommand extends Command {
private String name = "采集食物";
public GatherFoodCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.gatherFood();
}
@Override
public String getName() {
return name;
}
}
public class GatherGoldCommand extends Command {
private String name = "挖金矿";
public GatherGoldCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.gatherGold();
}
@Override
public String getName() {
return name;
}
}
public class GatherStoneCommand extends Command {
private String name = "挖石矿";
public GatherStoneCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.gatherStone();
}
@Override
public String getName() {
return name;
}
}
public class GatherWoodCommand extends Command {
private String name = "砍树";
public GatherWoodCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.gatherWood();
}
@Override
public String getName() {
return name;
}
}
public class ShowResourcesCommand extends Command {
private String name = "显示资源、建筑与单位";
public ShowResourcesCommand(Headquarters headquarters) {
super(headquarters);
}
@Override
public void executeCommand() {
headquarters.showResources();
}
@Override
public String getName() {
return name;
}
}
对外窗口(Invoker):GUI
public class GUI {
private ArrayList<Command> orders;
public GUI() {
this.orders = new ArrayList<>();
}
public void receivePlayerCommand(Command command) {
orders.add(command);
System.out.println("接收指令: " + command.getName() + " 时间:" + new Date());
}
public void cancelPlayerCommand(Command command) {
orders.remove(command);
System.out.println("取消指令: " + command.getName() + " 时间:" + new Date());
}
public void executePlayerCommands() {
for (Command command : orders) {
command.executeCommand();
}
}
}
测试,玩家尝试建造房屋、城堡,生产村民、游侠,采集木头、食物、黄金、石头,最後显示资源与单位数量:RTSCommandSample
public class RTSCommandSample {
public static void main(String[] args) {
Headquarters headquarters = new Headquarters();
Command createVillagerCommand = new CreateVillagerCommand(headquarters);
Command createPaladinCommand = new CreatePaladinCommand(headquarters);
Command createHouseCommand = new CreateHouseCommand(headquarters);
Command createCastleCommand = new CreateCastleCommand(headquarters);
Command gatherWoodCommand = new GatherWoodCommand(headquarters);
Command gatherFoodCommand = new GatherFoodCommand(headquarters);
Command gatherGoldCommand = new GatherGoldCommand(headquarters);
Command gatherStoneCommand = new GatherStoneCommand(headquarters);
Command showResourcesCommand = new ShowResourcesCommand(headquarters);
GUI gui = new GUI();
gui.receivePlayerCommand(createVillagerCommand);
gui.receivePlayerCommand(createPaladinCommand);
gui.receivePlayerCommand(gatherFoodCommand);
gui.receivePlayerCommand(gatherFoodCommand);
gui.receivePlayerCommand(gatherGoldCommand);
gui.receivePlayerCommand(gatherGoldCommand);
gui.receivePlayerCommand(createPaladinCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(gatherWoodCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.cancelPlayerCommand(createHouseCommand);
gui.cancelPlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createCastleCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.cancelPlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(createCastleCommand);
gui.receivePlayerCommand(showResourcesCommand);
gui.executePlayerCommands();
}
}
单位物件:Villager
、Paladin
、House
、Castle
class Villager {
/** @param {Headquarters} headquarters */
constructor(headquarters) {
this.healthPoints = 25;
this.headquarters = headquarters;
}
/** @param {number} damagePoints */
/** @param {number} damagePoints */
gotDamage(damagePoints) {
this.healthPoints -= damagePoints;
if (this.healthPoints < 0) {
this.headquarters.removeVillager();
}
}
}
class Paladin {
/** @param {Headquarters} headquarters */
constructor(headquarters) {
this.healthPoints = 160;
this.headquarters = headquarters;
}
/** @param {number} damagePoints */
gotDamage(damagePoints) {
this.healthPoints -= damagePoints;
if (this.healthPoints < 0) {
this.headquarters.removePaladin();
}
}
}
class House {
/** @param {Headquarters} headquarters */
constructor(headquarters) {
this.healthPoints = 550;
this.headquarters = headquarters;
}
/** @param {number} damagePoints */
gotDamage(damagePoints) {
this.healthPoints -= damagePoints;
if (this.healthPoints < 0) {
this.headquarters.removeHouse();
}
}
}
class Castle {
/** @param {Headquarters} headquarters */
constructor(headquarters) {
this.healthPoints = 4800;
this.headquarters = headquarters;
}
/** @param {number} damagePoints */
gotDamage(damagePoints) {
this.healthPoints -= damagePoints;
if (this.healthPoints < 0) {
this.headquarters.removeCastle();
}
}
}
特定物件(Receiver)
class Headquarters {
constructor() {
this.woodCounts = 100;
this.foodCounts = 100;
this.goldCounts = 50;
this.stoneCounts = 50;
/** @type {Villager[]} */
this.villagerList = [];
/** @type {Paladin[]} */
this.paladinList = [];
/** @type {House[]} */
this.houseList = [];
/** @type {Castle[]} */
this.castleList = [];
}
createVillager() {
if (this.foodCounts < 50) {
console.log("食物不足,无法生产村民\n");
} else {
console.log("食物充足,已生产村民\n");
this.villagerList.push(new Villager(this));
this.foodCounts -= 50;
}
}
removeVillager() {
if (this.villagerList.length === 0) {
console.log("没有村民可以删除");
} else {
this.villagerList.shift();
console.log("村民已删除");
}
}
createPaladin() {
if (this.foodCounts < 60) {
console.log("食物不足,无法生产游侠\n");
} else if (this.goldCounts < 75) {
console.log("黄金不足,无法生产游侠\n");
} else {
console.log("食物充足,已生产游侠\n");
this.paladinList.push(new Paladin(this));
this.foodCounts -= 60;
this.goldCounts -= 75;
}
}
removePaladin() {
if (this.paladinList.length === 0) {
console.log("没有游侠可以删除");
} else {
this.paladinList.shift();
console.log("游侠已删除");
}
}
createHouse() {
if (this.woodCounts < 25) {
console.log("木头不足,无法建造居住房舍\n");
} else {
console.log("木头充足,已建造居住房舍\n");
this.houseList.push(new House(this));
this.woodCounts -= 25;
}
}
removeHouse() {
if (houseList.length === 0) {
console.log("没有居住房舍可以删除");
} else {
this.houseList.shift();
console.log("居住房舍已删除");
}
}
createCastle() {
if (this.stoneCounts < 650) {
console.log("石头不足,无法建造城堡\n");
} else {
console.log("石头充足,已建造城堡\n");
this.castleList.push(new Castle(this));
this.stoneCounts -= 600;
}
}
removeCastle() {
if (this.castleList.length === 0) {
console.log("没有城堡可以删除");
} else {
this.castleList.shift();
console.log("城堡已删除");
}
}
gatherWood() {
if (this.villagerList.length === 0) {
console.log("没有村民可用\n");
} else {
console.log("村民数量足够,开始砍树\n");
this.woodCounts += 100;
}
}
gatherFood() {
if (this.villagerList.length === 0) {
console.log("没有村民可用\n");
} else {
console.log("村民数量足够,开始采集食物\n");
this.foodCounts += 100;
}
}
gatherGold() {
if (this.villagerList.length === 0) {
console.log("没有村民可用\n");
} else {
console.log("村民数量足够,开始挖金矿\n");
this.goldCounts += 100;
}
}
gatherStone() {
if (this.villagerList.length === 0) {
console.log("没有村民可用\n");
} else {
console.log("村民数量足够,开始挖石矿\n");
this.stoneCounts += 100;
}
}
showResources() {
console.log("---当前资源---");
console.log("木头: " + this.woodCounts);
console.log("食物: " + this.foodCounts);
console.log("黄金: " + this.goldCounts);
console.log("石头: " + this.stoneCounts);
console.log("---当前建筑数量---");
console.log("居住房舍: " + this.houseList.length);
console.log("城堡: " + this.castleList.length);
console.log("---当前单位数量---");
console.log("村民: " + this.villagerList.length);
console.log("游侠: " + this.paladinList.length);
console.log("---完毕---\n");
}
}
行为的虚拟层亲代:Command
/** @abstract */
class Command {
/** @param {Headquarters} headquarters */
constructor(headquarters) {
this.headquarters = headquarters;
}
/** @abstract */
executeCommand() { return; }
/** @abstract */
getName() { return; }
}
行为子代:CreateVillagerCommand
、RemoveVillagerCommand
、CreatePaladinCommand
、RemovePaladinCommand
、CreateHouseCommand
、RemoveHouseCommand
、CreateCastleCommand
、RemoveCastleCommand
、GatherFoodCommand
、GatherGoldCommand
、GatherStoneCommand
、GatherWoodCommand
、ShowResourcesCommand
(Command 物件)
class CreateVillagerCommand extends Command {
/** @param {Headquarters} headquarters */
constructor(headquarters) {
super(headquarters);
this.name = "生产村民";
}
/** @override */
executeCommand() {
this.headquarters.createVillager();
}
/** @override */
getName() {
return this.name;
}
}
class RemoveVillagerCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "删除村民";
}
/** @override */
executeCommand() {
this.headquarters.removeVillager();
}
/** @override */
getName() {
return this.name;
}
}
class CreatePaladinCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "生产游侠";
}
/** @override */
executeCommand() {
this.headquarters.createPaladin();
}
/** @override */
getName() {
return this.name;
}
}
class RemovePaladinCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "删除游侠";
}
/** @override */
executeCommand() {
this.headquarters.removePaladin();
}
/** @override */
getName() {
return this.name;
}
}
class CreateHouseCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "建造居住房舍";
}
/** @override */
executeCommand() {
this.headquarters.createHouse();
}
/** @override */
getName() {
return this.name;
}
}
class RemoveHouseCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "删除居住房舍";
}
/** @override */
executeCommand() {
this.headquarters.removeHouse();
}
/** @override */
getName() {
return this.name;
}
}
class CreateCastleCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "建造城堡";
}
/** @override */
executeCommand() {
this.headquarters.createCastle();
}
/** @override */
getName() {
return this.name;
}
}
class RemoveCastleCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "删除城堡";
}
/** @override */
executeCommand() {
this.headquarters.removeCastle();
}
/** @override */
getName() {
return this.name;
}
}
class GatherFoodCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "采集食物";
}
/** @override */
executeCommand() {
this.headquarters.gatherFood();
}
/** @override */
getName() {
return this.name;
}
}
class GatherGoldCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "挖金矿";
}
/** @override */
executeCommand() {
this.headquarters.gatherGold();
}
/** @override */
getName() {
return this.name;
}
}
class GatherStoneCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "挖石矿";
}
/** @override */
executeCommand() {
this.headquarters.gatherStone();
}
/** @override */
getName() {
return this.name;
}
}
class GatherWoodCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "砍树";
}
/** @override */
executeCommand() {
this.headquarters.gatherWood();
}
/** @override */
getName() {
return this.name;
}
}
class ShowResourcesCommand extends Command {
constructor(headquarters) {
super(headquarters);
this.name = "显示资源、建筑与单位";
}
/** @override */
executeCommand() {
this.headquarters.showResources();
}
/** @override */
getName() {
return this.name;
}
}
对外窗口(Invoker):GUI
class GUI {
constructor() {
/** @type {Command[]} */
this.orders = [];
}
receivePlayerCommand(command) {
this.orders.push(command);
console.log("接收指令: " + command.getName() + " 时间:" + new Date().toISOString());
}
cancelPlayerCommand(command) {
this.orders.filter((item) => item !== command);
let index = -1;
for (let i = 0; i < this.orders.length; i++) {
const item = this.orders[i];
if (item.getName() === command.getName()) {
index = i;
break;
}
}
if (index >= 0) {
this.orders.splice(index, 1);
}
console.log("JSON.stringify(this.orders) " + JSON.stringify(this.orders))
console.log("取消指令: " + command.getName() + " 时间:" + new Date().toISOString());
}
executePlayerCommands() {
for (const command of this.orders) {
command.executeCommand();
}
}
}
测试,玩家尝试建造房屋、城堡,生产村民、游侠,采集木头、食物、黄金、石头,最後显示资源与单位数量:rtsCommandSample
const rtsCommandSample = () => {
const headquarters = new Headquarters();
const createVillagerCommand = new CreateVillagerCommand(headquarters);
const createPaladinCommand = new CreatePaladinCommand(headquarters);
const createHouseCommand = new CreateHouseCommand(headquarters);
const createCastleCommand = new CreateCastleCommand(headquarters);
const gatherWoodCommand = new GatherWoodCommand(headquarters);
const gatherFoodCommand = new GatherFoodCommand(headquarters);
const gatherGoldCommand = new GatherGoldCommand(headquarters);
const gatherStoneCommand = new GatherStoneCommand(headquarters);
const showResourcesCommand = new ShowResourcesCommand(headquarters);
const gui = new GUI();
gui.receivePlayerCommand(createVillagerCommand);
gui.receivePlayerCommand(createPaladinCommand);
gui.receivePlayerCommand(gatherFoodCommand);
gui.receivePlayerCommand(gatherFoodCommand);
gui.receivePlayerCommand(gatherGoldCommand);
gui.receivePlayerCommand(gatherGoldCommand);
gui.receivePlayerCommand(createPaladinCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.receivePlayerCommand(gatherWoodCommand);
gui.receivePlayerCommand(createHouseCommand);
gui.cancelPlayerCommand(createHouseCommand);
gui.cancelPlayerCommand(createHouseCommand);
gui.receivePlayerCommand(createCastleCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(gatherStoneCommand);
gui.cancelPlayerCommand(gatherStoneCommand);
gui.receivePlayerCommand(createCastleCommand);
gui.receivePlayerCommand(showResourcesCommand);
gui.executePlayerCommands();
}
rtsCommandSample();
Command 模式是十分常见,将「行为请求者」与「行为执行者」切开来,避免两者过度耦合,增加开发上的弹性。
但是缺点十分明显,程序码为了实践分离目的,需要增加许多的程序码,同时增加程序的复杂度。部份文章指出为了实践设计模式会增加繁杂的设计、复杂度等等,今天总算体验到了。
明天将介绍 Behavioural patterns 的第三个模式:Interpreter 模式。
<<: Day 19 Knative Serving DNS 测试
>>: 不只懂 Vue 语法:试解释 hash 与 history 模式的分别? 为何 history 模式会回传 404?
这次要藉由websocket做出网站实时的线上人数,关於django的websocket设定就不赘述...
前言 前两篇我们介绍了如何在 Go 对 MySQL 和 Scylla 做操作,而这两个皆为较具规模的...
选模型并非最重要 为什麽我们要以回归分析的方式来建立模型,其他方式可不可以?其实没有说不行。 然而回...
大家好,我是YIYI,今天我要来制作HOMEPAGE中MONTH与TODAY的切换以及右下角的加号点...
本系列文之後也会置於个人网站 在这之前,都是先请大家照着做,没有好好说明关於Keycloak的使用...