灵活的装饰图案?

时间:2008-10-09 09:19:26

标签: design-patterns decorator

我正在寻找一种模式来模拟我正在考虑在个人项目中做的事情,我想知道装饰模式的修改版本是否会起作用。

基本上我正在考虑创建一个游戏,其中角色属性被他们所配置的项目修改。装饰器堆叠它的修改的方式是完美的,但是我从来没有见过允许你删除中间装饰器的装饰器,这是物品没有装备时会发生的情况。

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

澄清

要解释“中级装饰者”,例如我的基类是装饰着用糖装饰的牛奶的咖啡(使用头部第一个设计图案中的例子)牛奶将是装饰基础咖啡的中间装饰者,并由糖装饰。

更多澄清:)

这个想法是项目改变了统计数据,我同意我正在将装饰者变成这个。我会看看状态包。基本上我想要一个单点调用统计数据,并且当项目配备/不配备时,它们可以上下移动。

我可以将修改器应用于装备上的角色统计数据,并在不等时将其回滚。或者,当要求统计数据迭代所有项目并计算统计数据时。

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

8 个答案:

答案 0 :(得分:2)

说实话,听起来你真的想要一个你并不真正需要的模式,只是为了使用一个模式。不要那个人。

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

答案 1 :(得分:2)

我看到你正在尝试做什么,但要记住关于模式的一件事是,你不应该试图用你的设计来装饰图案。模式自然发生 - 您描述的行为实际上并不是Decorator模式的一部分。

话虽如此,我想你会想要通过一些独特的ID来取消武器,比如说:

Character.unequip(LIGHTSABER);

如果您尝试将其装入装饰器模式,则必须跟踪当前装备的物品,然后在移除武器后,您必须更新装饰LIGHTSABER的物体的参考一个LIGHTSABER正在装饰。这是很多工作。

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

答案 2 :(得分: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...
 }
}

当然,这只是一个建议,绝对可以辩论,我不是说这是最好或唯一的方法来做到这一点......

答案 3 :(得分: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)可能有点矫枉过正。

答案 4 :(得分:1)

只需保留2组统计数据,基本统计数据和有效统计数据。装备或装备物品时,在适当的情况下增加或减少有效统计数据。然后,每当您想知道自己的统计数据时,就不必遍历设备清单。

答案 5 :(得分:1)

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

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

撰写您的实体/游戏对象。对于在游戏中构造实体行为,永远不要依赖继承,或者依赖于任何依赖于继承的任何东西 - 这包括OP建议的装饰模式。你将自己动手。作文是要走的路。

答案 6 :(得分:0)

您在寻找策略模式吗?

答案 7 :(得分:0)

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

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

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