gpt4 book ai didi

c# - 策略模式和 "action"类爆炸

转载 作者:太空狗 更新时间:2023-10-29 21:31:07 25 4
gpt4 key购买 nike

有很多只做一件事的“工作”类(例如策略类)是不是不好的策略?

假设我想创建一个 Monster 类。我不会只在一个类中定义我想要的关于怪物的所有内容,而是尝试确定它的主要特征是什么,这样我就可以在接口(interface)中定义它们。这将允许:

  1. 如果我愿意,可以封课。之后,其他用户可以通过我定义的接口(interface)创建一个新类并且仍然具有多态性。我不必担心人们(或我自己)将来可能会如何更改/添加功能到基类。所有类都继承自 Object,它们通过接口(interface)实现继承,而不是从母类继承。
  2. 为游戏世界中的其他成员重复使用我对这个怪物使用的策略。

缺点:这个模型很僵硬。有时我们想定义一些仅通过尝试将这些“积木”放在一起就不容易实现的东西。

public class AlienMonster : IWalk, IRun, ISwim, IGrowl {
IWalkStrategy _walkStrategy;
IRunStrategy _runStrategy;
ISwimStrategy _swimStrategy;
IGrowlStrategy _growlStrategy;

public Monster() {
_walkStrategy = new FourFootWalkStrategy();
...etc
}

public void Walk() { _walkStrategy.Walk(); }
...etc
}

接下来我的想法是制定一系列不同的策略,供不同的怪物使用。另一方面,它们中的一些也可以用于完全不同的目的(即,我可以有一个也能“游泳”的坦克)。我看到这种方法的唯一问题是它可能导致纯“方法”类的爆炸式增长,即,策略类的唯一目的是执行这个或那个其他操作。另一方面,这种“模块化”允许策略的高度重用,有时甚至在完全不同的上下文中也是如此。

您对此事有何看法?这是一个有效的推理吗?这是过度工程化吗?

此外,假设我们对我上面给出的示例进行了适当的调整,那么将 IWalk 定义为是否会更好:

interface IWalk {
void Walk();
}

interface IWalk {
IWalkStrategy WalkStrategy { get; set; } //or something that ressembles this
}

因为这样做我不需要在 Monster 本身上定义方法,我只需要 IWalkStrategy 的公共(public) getter(这似乎违背了你应该尽可能多地封装所有东西的想法!)为什么?

谢谢

最佳答案

Walk、Run 和 Swim 似乎是实现而不是接口(interface)。您可以拥有一个 ILocomotion 接口(interface)并允许您的类接受 ILocomotion 实现的列表。

Growl 可以是 IAbility 接口(interface)之类的实现。一个特定的怪物可能有一组 IAbility 实现。

然后有几个接口(interface)是使用哪种能力或运动的逻辑:例如 IMove、IAct。

public class AlienMonster : IMove, IAct
{
private List<IAbility> _abilities;
private List<ILocomotion> _locomotions;

public AlienMonster()
{
_abilities = new List<IAbility>() {new Growl()};
_locomotion = new List<ILocomotion>() {new Walk(), new Run(), new Swim()}
}

public void Move()
{
// implementation for the IMove interface
}

public void Act()
{
// implementation for the IAct interface
}

}

通过以这种方式编写您的类(class),您将避免一些死板。

编辑:添加了有关 IMove 和 IAct 的内容

编辑:经过一些评论

通过将 IWalk、IRun 和 ISwim 添加到怪物中,您是在说任何可以看到该对象的东西都应该能够调用在任何这些接口(interface)中实现的任何方法,并使其有意义。此外,为了让某些东西决定它应该使用三个接口(interface)中的哪一个,你必须传递整个对象。使用接口(interface)的一个巨大优势是您可以通过该接口(interface)引用它。

void SomeFunction(IWalk alienMonster) {...}

上述函数将接受任何实现 IWalk 的函数,但如果 IRun、ISwim 等有 SomeFunction 的变体,您必须为每个函数编写一个全新的函数,或者将整个 AlienMonster 对象传递给它。如果您传入该对象,则该函数可以调用其上的任何和所有接口(interface)。这也意味着该函数必须查询 AlienMonster 对象以查看其功能,然后决定使用哪个。所有这一切最终使外部产生了许多本应保留在类内部的功能。因为您将所有这些外部化,并且 IWalk、IRun、ISwim 之间没有共性,所以某些函数可以无辜地调用所有这三个接口(interface),并且您的怪物可以同时进行运行-步行-游泳。此外,由于您希望能够在某些类上调用 IWalk、IRun、ISwim,所有类基本上都必须实现所有三个接口(interface),并且您最终会制定像 CannotSwim 这样的策略来满足 ISwim 的接口(interface)要求,当一个怪物不会游泳。否则你最终可能会尝试调用一个没有在怪物上实现的接口(interface)。最后,您实际上是在为额外的接口(interface)让代码变得更糟,IMO。

关于c# - 策略模式和 "action"类爆炸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2618732/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com