【问题标题】:How to implement mutable functionality at runtime? [closed]如何在运行时实现可变功能? [关闭]
【发布时间】:2017-03-17 22:08:50
【问题描述】:

我正在制作一款游戏,在该游戏中,玩家角色可以获得改变其角色在我的世界模型中的行为方式或为其添加功能的特性。例如,角色可能会获得改变坠落伤害计算方式的“羽毛”特性或意味着玩家现在可以拾取以前只是场景一部分的物品的“强壮”特性。

我一直在他们的相关类中对特征进行硬编码,并在它们起作用时切换一个布尔值来改变行为,但是随着我的特征列表的增长,它变得相当难以管理。必须有一种更具可扩展性和解耦的方式来做到这一点。

(我想要的完美场景是一种方式,我可以对类变体进行编程并在运行时以某种方式切换它们,同时保持前一个对象的上下文和引用,但任何其他方式都可以适当地满足以下要求是一个很好的答案。)

您将如何实现这样一个功能,即在运行时更改方法并获得和删除新功能?(请提供给定场景的假设示例)如果您不倾向于为我做我的工作,哪种编程模式会你用什么来实现这种行为?

P.S.:请随时提出更好的标题。我讨厌那些。一旦找到更好的,我将编辑它。

【问题讨论】:

标签: design-patterns polymorphism


【解决方案1】:

您可以尝试实现Decorator Pattern,它通常用于动态添加和删除对象的行为,而不更改原始对象的引用。维基百科页面为您提供了很好的解释和示例。 无论如何,我会尝试向您展示一个简单的 Java(希望您能理解它,您没有指定语言)示例可能更接近您的情况。 假设你有一个这样的字符类:

public class Character {

    public int calculateFallDamage() {
         return 10;
    }

    public void pickUpItem() {
    // initially this method could be empty
    // nothing happens when you try to pick up items
    }
}

现在我们创建一个添加“羽毛”特征的 Character 子类。这个子类必须包含它扩展的类的一个字段,以改变它的行为:

public class FeatherDecorator extends Character {

    private Character decoratedCharacter;

    public FeatherDecorator(Character character) {
        this.decoratedCharacter = character;
    }

    @Override
    public int calculateFallDamage() {
        int fallDamage = decoratedCharacter.calculateFallDamage();  // call the function of the decorated class
        return fallDamage - 5;  // change the result 
    }
}

如果您想添加“羽毛”特征,您可以创建一个新对象,如下所示:

Character character = new Character();
int fallDamage = character.calculateFallDamage(); // returns 10
character = new FeatherDecorator(character);
int newFallDamage = character.calculateFallDamage(); // returns 5

这样做你可以保留对 Object 的原始引用,但同时你可以改变他的行为。如果您有兴趣删除装饰,可以添加如下方法:

public class Character() {
    ...
    public Character getDecoratedComponent() {
    // exception becaus it's not decorated
    }
    ...
}

public class FeatherDecorator extends Character {

    private Character decoratedCharacter;
    ...
    @Override
    public Character getDecoratedComponent() {
        return decoratedCharacter;
    }
    ...
}

现在很容易得到没有装饰的原始对象:

Character character = new FeatherDecorator(new Character());
character = character.getDecoratedComponent(); // returns the object without the feater decorator

希望对你有所帮助,装饰器模式是一种非常强大的模式,它为对象的行为提供了一定的灵活性。如果您需要更多解释,请告诉我。

【讨论】:

  • 这正是我想要的两个警告,也许你也可以帮助我。我的第一个问题是,据我所知,我可以添加任意数量的特征。例如,我可以添加羽毛特征,然后添加强特征,它会起作用。但是如果我想删除一个特征,我只能删除最后添加的。就像在堆栈中一样。我看到的第二个问题是否假设存在对字符对象的单个引用。有没有办法一次更新所有参考资料?
  • 如果你想移除特定的装饰,你可以查看this question。很抱歉,但我不明白你可以对同一个对象有许多不同的引用,这个事实可能会导致装饰器模式出现问题。在这种情况下,正如 jaco0646 在评论中所说,State Pattern 可能会更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 2013-05-06
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
相关资源
最近更新 更多