dev*_*ium 6 c# oop design-patterns
拥有大量"工作"类(例如策略类)是不是很糟糕,只做一件事?
让我们假设我想制作一个怪物类.我不会仅仅在一个类中定义关于怪物的所有内容,而是尝试确定它的主要特征是什么,因此我可以在接口中定义它们.这将允许:
Con:这个模型很僵硬.有时候我们想要通过组合这个"构建块"来定义一些不容易实现的东西.
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
}
我的想法是接下来制作一系列可以被不同怪物使用的不同策略.另一方面,其中一些也可以用于完全不同的目的(即,我可以有一个也"游泳"的坦克).我用这种方法看到的唯一问题是,它可能会导致纯粹的"方法"类的爆炸,即,策略类只有作为这个或那个其他动作的目的.另一方面,这种"模块化"将允许高度重用stratagies,有时甚至在完全不同的环境中.
你对这件事有什么看法?这是一个有效的推理吗?这是否过度工程?
另外,假设我们对上面给出的示例进行了适当的调整,将IWalk定义为:
interface IWalk {
    void Walk();
}
要么
interface IWalk {
    IWalkStrategy WalkStrategy { get; set; } //or something that ressembles this
}
为了做到这一点,我不需要在Monster本身定义方法,我只是为IWalkStrategy提供公共getter(这似乎违背了你应该尽可能多地封装所有内容的想法!)为什么?
谢谢
Walk、Run 和 Swim 似乎是实现而不是接口。您可以拥有一个 ILocomotion 接口并允许您的类接受 ILocomotion 实现的列表。
Growl 可以是 Iability 接口之类的实现。特定的怪物可以拥有 IAbility 实现的集合。
然后有几个接口,它们是使用哪种能力或运动的逻辑:例如 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
  }
}
通过以这种方式组成你的课程,你将避免一些僵化。
编辑:添加了有关 IMove 和 IAct 的内容
编辑:经过一些评论
通过将 IWalk、IRun 和 ISwim 添加到怪物中,您可以说任何可以看到该对象的对象都应该能够调用在任何这些接口中实现的任何方法,并使其有意义。此外,为了让某些东西决定应该使用三个接口中的哪一个,您必须传递整个对象。使用接口的一大优点是您可以通过该接口引用它。
void SomeFunction(IWalk alienMonster) {...}
上面的函数将采用任何实现 IWalk 的函数,但如果 IRun、ISwim 等有 SomeFunction 的变体,则您必须为每个函数编写一个全新的函数,或者传递整个 AlienMonster 对象。如果您传入该对象,则该函数可以调用其上的任何和所有接口。这也意味着该函数必须查询 AlienMonster 对象以查看其功能,然后决定使用哪个。所有这些最终都会使许多本应保留在类内部的功能变得外部化。因为你正在外部化所有这些,并且 IWalk、IRun、ISwim 之间没有共性,所以某些函数可能会无意中调用所有三个接口,并且你的怪物可能会同时跑步、行走、游泳。此外,由于您希望能够在某些类上调用 IWalk、IRun、ISwim,因此所有类基本上都必须实现所有三个接口,并且您最终将制定像 CannotSwim 这样的策略来满足当怪物出现时 ISwim 的接口要求不会游泳。否则,您最终可能会尝试调用未在怪物上实现的接口。最后,我认为,对于额外的接口,您实际上使代码变得更糟。