2

我正在寻找一种模式来模拟我正在考虑在个人项目中做的事情,并且我想知道修饰器模式的修改版本是否可以工作。

基本上我正在考虑创建一个游戏,其中角色属性通过他们装备的物品进行修改。装饰器堆叠其修改的方式非常适合这一点,但是我从未见过允许您删除中间装饰器的装饰器,当物品未装备时会发生这种情况。

有没有人以这种方式使用装饰器模式的经验?还是我在叫错树?

澄清

解释“中间装饰器”,例如,如果我的基类是用牛奶装饰的咖啡,用糖装饰的牛奶(使用 Head first 设计模式中的示例)牛奶将是中间装饰器,因为它装饰了基础咖啡,并被装饰由糖。

还有更多的澄清:)

这个想法是物品会改变统计数据,我同意我将装饰器硬塞进这个。我会查看状态袋。本质上,我想要一个统计数据点,并在装备/不装备物品时让它们上升/下降。

我可以将修改器应用于装备时的角色统计数据,并在取消装备时将它们回滚。或者每当要求统计数据时,遍历所有项目并计算统计数据。

我只是在这里寻找反馈,我知道我可能正在使用电锯,剪刀更合适......

4

8 回答 8

2

老实说,这听起来像是你真的在试图适应一个你并不真正需要的模式,只是为了使用一个模式。不要成为那个人。

现在,如果武器给了角色一些额外的力量/耐力/生命值或其他什么,那么它可能值得考虑。但听起来你根本不会用这些来修改(或装饰)角色的属性。

于 2008-10-09T11:32:41.017 回答
2

我明白你想要做什么,但是关于模式要记住的一件事是,你不应该试图把你的设计硬塞进一个模式。模式自然发生 - 您描述的行为实际上并不是装饰器模式的一部分。

话虽如此,我想你会想通过一些独特的 ID 来解除武器装备,比如:

Character.unequip(LIGHTSABER);

如果您尝试将其放入装饰器模式中,则必须跟踪当前装备的物品,然后在移除武器后,您必须将装饰光刃的对象的引用更新为LIGHTSABER 正在装饰。这是很多工作。

相反,也许值得考虑@Mitch 的想法,让角色的武器在财产袋中有所帮助。请记住,一个角色拥有一套武器。对我来说,似乎组合可能是要走的路。

于 2008-10-09T11:39:46.073 回答
1

嗯..我在想也许命令模式会是解决这个问题的好方法。这就是我的意思:

这是你的角色类:

Public class Character {

 //various character related variables and methods here...

 Command[] equipCommands;
 Command[] unequipCommands;

 public Character(Command[] p_equipCommands, Command[] p_unequipCommands) {

  equipCommands = p_equipCommands;
  unequipCommands = p_unEquipCommands;
 }

 public void itemEquiped(int itemID) {

  equipCommands[itemID].execute(this);
 }

 public void itemUnequiped(int itemID) {

  unequipCommands[itemID].execute(this);
 }
}

以下是一些命令示例:

public class SwordOfDragonSlayingEquipCommand implements ItemCommand{

 public void execute(Character p_character) {

  //There's probably a better way of doing this, but of the top of my head...
  p_character.addItemToInventory(Weapons.getIteM(Weapons.SWORD_OF_DRAGON_SLAYING));

  //other methods that raise stats, give bonuses etc. here...
 }
}

public class SwordOfDragonSlayingUnequipCommand implements ItemCommand{

 public void execute(Character p_character) {

  //There's probably a better way of doing this, but of the top of my head...
  p_character.removeItemFromInventory(Weapons.getIteM(Weapons.SWORD_OF_DRAGON_SLAYING));

  //other methods that lower stats, remove bonuses etc. here...
 }
}

当然,这只是一个建议,绝对可以讨论,我并不是说这是最好的或唯一的方法......

于 2008-10-11T12:33:56.090 回答
1

在视频游戏中实现传播的统计数据有三个答案:

(1) 这将满足您将制作的任何业余爱好者游戏(以及几乎所有职业游戏):

character.GetStrength() {
  foreach(item in character.items)
    strFromItems += item.GetStrengthBonusForItems();
       foreach(buff in character.buffs)
    strFromBuffs += buff.GetStrengthBonusForBuffs();
  ...

  return character.baseStrength + strFromItems + ...;
}

(注意不同的 GetStrength*() 函数彼此无关)

(2) 这将满足所有标题中没有“暗黑破坏神”一词的游戏:

 character.GetStr() { ... // same as above, strength is rarely queried }
 character.GetMaxHP() { 
   if (character._maxHPDirty) RecalcMaxHP();
   return character.cachedMaxHP;
 }
 // repeat for damage, and your probably done, but profile to figure out
 // exactly which stats are important to your game

(3) 其他

 // changes in diablo happen very infrequently compared to queries, 
 // so up propegate to optimize queries.  Moreover, 10 people edit 
 // the stat calculation formulas so having the up propegation match 
 // the caculation w/o writing code is pretty important for robustness.

 character.OnEquip(item) {
     statList.merge(item.statlist);
 }

 character.GetStrength() {
     statList.getStat(STRENGTH);
 }

 statlist.getStat(id) {
     if (IS_FAST_STAT(id)) return cachedFastStats[id];
     return cachedStats.lookup(id);
 }

 statlist.merge(statlist) {
      // left for an exercise for the reader
 }

老实说(3)可能是矫枉过正。

于 2008-10-11T19:15:16.497 回答
1

只需保留 2 组统计数据,即您的基本统计数据和有效统计数据。当您装备或取消装备物品时,在适当的情况下从有效统计数据中添加或减少。这样您就不必每次想知道您的统计数据时都遍历您的设备列表。

于 2008-10-12T13:18:39.010 回答
1

我知道这个问题已经过时了,但是如果不是 OP,这可能会对其他人有所帮助。阅读这篇文章,了解如何在游戏中真正做到这种事情(由参与 Tony Hawk 游戏的开发人员之一):

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

组合您的实体/游戏对象。为了在游戏中构建实体行为,永远,永远不要依赖继承,或者任何本身以任何方式依赖继承的东西——这包括 OP 建议的装饰器模式。你会束缚自己的双手。组合是要走的路。

于 2010-03-24T23:26:17.850 回答
0

您在寻找策略模式吗?

于 2008-10-11T20:52:09.203 回答
0

为什么不对武器进行如下编码:

1 = 电锯 2 = 霰弹枪 4 = 轨道枪

所以现在6的总和只能意味着角色拥有霰弹枪和轨道炮。这是一个快速摘要,因此您不必遍历您的武器字典列表。你仍然需要一些结构来容纳武器,但至少你会通过这种方法获得速度。这假定您只能拥有每个类别的一种武器,但同时可以拥有许多类别。

于 2008-10-13T00:45:31.743 回答