javascript - 功能 "real-time"组成

标签 javascript functional-programming state

我最近遇到了一个 great article涵盖对象组合与传统继承的优势。

希望我的问题不会被标记为固执己见,但我想知道在对象根据用户的游戏交互发生变化时使用组合的好方法。

以文章代码为例:

const canCast = (state) => ({
    cast: (spell) => {
        console.log(`${state.name} casts ${spell}!`);
        state.mana--;
    }
})

const canFight = (state) => ({
    fight: () => {
        console.log(`${state.name} slashes at the foe!`);
        state.stamina--;
    }
})

const fighter = (name) => {
  let state = {
    name,
    health: 100,
    stamina: 100
  }

  return Object.assign(state, canFight(state));
}

const mage = (name) => {
  let state = {
    name,
    health: 100,
    mana: 100
  }

  return Object.assign(state, canCast(state));
}

scorcher = mage('Scorcher')
scorcher.cast('fireball');    // Scorcher casts fireball!
console.log(scorcher.mana)    // 99

slasher = fighter('Slasher')
slasher.fight();              // Slasher slashes at the foe!
console.log(slasher.stamina)  // 99

如何使用组合在运行时更改 Character 对象的状态?我希望 Character 对象根据游戏事件发生变化,而不是已经存在的 Mage 对象。 Angular 色拿起一根法杖,现在变成了可以施法的“法师”。首先想到的是在 Angular 色中拥有一个状态属性,该状态属性会根据交互而变化,并且 Angular 色以某种方式“继承”现在施放的能力并获得法力状态属性。

最佳答案

decorator pattern完全像这样解决情况。

class Character {
  constructor(name) {
    this.name = name;
    this.health = 100;
    this.items = [];
  }
}

const fighterDecorator = character => {
  return Object.setPrototypeOf({
    character,
    stamina: 100,
    fight() {
      console.log(`${this.name} slashes at the foe!`);
      this.stamina--;
    }
  }, character);
}

const mageDecorator = character => {
  return Object.setPrototypeOf({
    character,
    mana: 100,
    cast(spell) {
      console.log(`${this.name} casts ${spell}!`);
      this.mana--;      
    }
  }, character);
}

let character = new Character("Bob");

// Can't fight; can't cast
// character.fight(); // TypeError: not a function
// character.cast(); // TypeError: not a function

// Character becomes a fighter at runtime
// Equiping an item and decorating new behavior are separate statements
character.items.push("sword");
character = fighterDecorator(character);
character.fight();              // Bob slashes at the foe!
console.log(character.stamina)  // 99
console.log(character.items)    // ["sword"]

// Character becomes normal unit again
// Remove decoration and remove item
character = character.character;
character.items = character.items.filter(item => item !== "sword");

// Once again, can't fight, can't cast
// character.fight(); // TypeError: not a function
// character.cast(); // TypeError: not a function

// Character becomes a mage at runtime
// Equiping an item and decorating new behavior are separate statements
character.items.push("staff");
character = mageDecorator(character);
character.cast("fireball");  // Bob casts fireball!
console.log(character.mana)  // 99
console.log(character.items) // ["staff"]

关于javascript - 功能 "real-time"组成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50844719/

相关文章:

scala - 猫,减少 EitherT 的 Seq

user-interface - 为什么此FAB无法更新状态?

reactjs - 如何清理 Redux 的状态?

javascript - 在 Orchard cms 中,我想包含某些 .js 文件,我应该把它们放在哪里,我应该如何将它包含在我的项目中?

javascript - Angular-Chart 无法读取未定义的属性 'skip'

javascript - Facebook 永久访问 token

javascript - 是否可以绑定(bind)一个javascript函数,使其本地上下文与 'this'相同?

javascript - 动态 iframe 链接

algorithm - 如何在 Haskell 中标记树中的节点?

flutter - 如果页面已更改,Flutter应用程序复选框将停止切换状态