【问题标题】:Architecture for Interface/Abstraction接口/抽象架构
【发布时间】:2015-03-18 19:08:56
【问题描述】:

我遇到了我最不喜欢的问题,那就是重写代码。这是我目前设计的结构。

public interface ICanMove
{
    int speed { get; set; }

    void Walk();
    void Run();
}

public class Worker : ICanMove
{
    speed = 5;

    public void Walk()
    {
    //Example code Move(speed);
    }
}

public class Warrior : ICanMove
{
    speed = 3;

    public void Walk()
    {
    //Example code Move(speed);
    }
}

这里的问题是多个类以相同的方式使用接口。但他们不会总是以同样的方式做事。有没有办法实现这个..更正确。我的另一个选项是一个抽象类,它适用于这个例子,但当我有更多接口时(ICanAttack,ICanBuild)

带抽象类

public abstract class LivingCreature : ICanMove
{
    public abstract int speed {get;set;}

    public void Walk()
    {
       //Example code Move(speed);
    }

    public void Run()
    { 

    }
}

但是我的问题变成了我必须在一个基类上实现多个接口,并不是每个从该基类继承的对象都需要 100%

【问题讨论】:

  • 如果您不希望他们以不同的方式实现它,那么您将使用您提到的抽象类。
  • 进一步扩展我的评论——界面是您可以做某事的保证,但不能保证您如何做到这一点。抽象类提供通常共享的功能。您可以创建一个实现接口的抽象类,然后从抽象类继承。
  • 如果你创建一个抽象类,比如BaseMover,你可以让抽象类实现ICanMove,然后让Worker和Warrior派生自IBaseMover。问题是您不能进行多重继承,因此拥有 BaseMover 意味着您还可以继承标准化 IcanBuild 接口实现的 BaseBuilder。
  • 也许你的ICanMove 没有步行和跑步,而是只有步行和跑步所需的属性(所以这里只是速度)。然后创建一个实现 Walk 和 Run 的移动器类,其中每个方法都接收一个 ICanMove 对象。如果您需要以不同的方式移动,那么您可以创建一个 IMover 界面,然后创建不同的步行/跑步组合

标签: c# .net interface abstract-class


【解决方案1】:

我建议遵循这种方法的策略模式。

You're Walk/Run 应该是运动的界面。

例如,您可能有一个只能“滚动”而不能跑/走的机器人。所以那个机器人的动作应该是Roll。

下本书的第一章将帮助您了解与当前代码示例相关的这种模式。

http://www.amazon.ca/Head-First-Design-Patterns-Freeman/dp/0596007124(这是用 Java 编写的,但很容易翻译成 C#)这本书也在许多网站上免费提供。

在线版(免费):http://www.dcc.ufrj.br/~comp2/TextosJava/Head%20First%20-%20Design%20Patterns.pdf

这个 SO question 还讨论了 Ducks and Flying 的策略模式。这一页也是本书的一部分。 Duck example strategy pattern - Head first design pattern

例如:

public interface IMovement
{
    int speed { get; set; }
}

public class Worker
{
    speed = 5;
    IMovement Movement;
   public Warrior(IMovement m)
    {
        this.Movement = m;
    }
    public void Move()
    {
      this.Movement.Move();
    }
}

public class Warrior
{
    speed = 3;
    IMovement movement;

    public Warrior(IMovement m)
    {
        this.Movement = m;
    }

    public void Move()
    {
      this.Movement.Move();
    }
}

void foo()
{
     IMovement m = new FlyingMovement();
     Worker w = new Worker(m);

    IMovement swimmingMovement = new SwimmingMovement();
     SwimmingWorker sw = new SwimmingWorker (swimmingMovement);
}

对不起,我正在使用手机自动取款机。但是,这将为您的代码提供更多功能。

【讨论】:

  • :) 我通常会等 24 小时再做。只为你我会:)
【解决方案2】:

(在酒吧 atm 的平板电脑上,请原谅拼写错误和缺少代码示例)

嗯,这个类比可以沿着超级英雄的路线运行:他们都有许多特殊能力,但都是任意的和不同的。这些能力是由外部事件“赋予”他们的(彼得帕克可以爬墙,因为他被蜘蛛咬了)。

因此,您的类结构可能是这样的,即您有一个 iHasAbility 接口,该接口实现了一个 iAbility 列表。您可以通过 'Bestow(liability)' 方法赋予这些能力,然后通过某种方式来实施这些能力......'Enact("climbwall")'。

所以...组合而不是抽象。能力变得抽象而不是主题。

希望这会有所帮助,甚至只是激发一个想法。

【讨论】:

    【解决方案3】:

    另一种方法可能是使用辅助类(前几天我读到了一个很好的例子,使用 Michael knight 和 kitt。成功了)。

    所以你有一个类 (Iperson),它可以通过实现类似“influence(Iperson)”的任意类来帮助。

    “warriorhelper”助手可以通过“strikefoe”影响人,而builderhelper可以通过“buildhome”影响人。

    再次,希望这会有所帮助!

    附言。仍然在平板电脑上的酒吧。请原谅拼写错误和缺少代码示例。

    【讨论】:

      猜你喜欢
      • 2011-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      相关资源
      最近更新 更多