如何处理继承类的差异?

时间:2012-03-29 08:52:27

标签: .net design-patterns inheritance

我必须实施一些行动。每个都有一些共同的元素,所以它们应该从一个类继承。可以说,他们做了一些网络动作,所以基类是

public class WebAction
{
    private ServerData _serverData;
    public WebAction(ServerData serverData)
    {
        _serverData = serverData;
    }
}

此外,每个动作都需要执行,因此在基类I中也应该有某种Execute()方法。问题是,这个对象中的每一个都做了一些不同的事情,所以它应该采用不同的参数。我的问题是 - 女巫方式最适合达到此目的?

起初我正在思考一些配置对象,例如。 Execute(IWebActionConfig config)。在这种情况下,我可以使用像:

这样的对象
 LoginWebAction loginWebAction = LoginWebAction(staticServerConfig);
 LoginWebActionConfig = new LoginWebActionConfig { someData = "foo" };
 loginWebAction.Execute(loginWebActionConfig);

但是有没有意义创建一个额外的对象树?也许通过属性配置WebAction的每个子节点会更好吗?

LoginWebAction loginWebAction = LoginWebAction(staticServerConfig);
loginWebAction.someData = "foo";
// Execute will throw exception when someData not set
loginWebAction.Execute();

这些(如果有的话)方式更好吗?

3 个答案:

答案 0 :(得分:1)

我想你可以在这里使用Command Pattern。 您可以创建封装“Action”的不同命令(每个Web操作一个命令),每个命令都将包含所需的所有参数。

命令处理程序将包含用于执行该命令的“逻辑”。

有关命令模式的更多信息:

http://www.codeguru.com/csharp/.net/net_general/patterns/article.php/c15663/Implement-a-Command-Pattern-Using-C.htm

http://danielshitrit.blogspot.co.uk/2011/11/best-practices-command-pattern-in-c.html

答案 1 :(得分:1)

由于每个操作采用不同的参数,因此您无法使用多态来调用它们。换句话说,在类上调用Execute的方法必须知道它将调用Execute的类的确切类型。

所以,我会怀疑在这里使用继承是否真的是正确的解决方案。

您声明您正在使用继承,因为每个类都有一些共享代码。这通常不是使用继承的充分理由。我认为它是一种反模式。

使用继承的问题在于您将基类与派生类紧密耦合。这可能会导致单元测试和将来的维护出现问题。

我建议值得创建一个包含共享功能的单独类。然后你的Action类包含这个类作为成员并根据需要调用。这将允许您模拟此基类以进行测试。然后,每个类都可以拥有自己的Execute方法,每个方法都带有所需的参数。

答案 2 :(得分:0)

可以采用更多OOP风格。 look at NVI pattern

public class WebAction
{
  private ServerData _serverData;
  public WebAction(ServerData serverData)
  {
    _serverData = serverData;
  }
  public virtual ExecuteAction{};
  public Execute()
  {
     ExecuteAction();
     //to do the rest of base code 

  }
}
public class WebActionDerived1: WebAction
{
   WebActionDerived1(ServerData serverData, object arg1/*any unique param*/)
   :base(serverData)
   {
      _my_arg1 = arg1;
   }
   public override ExecuteAction
   {
    //call any procedure with your _my_arg1;
   }
}
public class WebActionDerived2: WebAction
{
   WebActionDerived1(ServerData serverData, string arg1,
   string arg2/*otherunique param*/)
   :base(serverData)
   {
      _my_arg1 = arg1;
      _my_arg2 = arg2;
   }
   public override ExecuteAction
   {
    //call any procedure with your _my_arg1, and _my_arg2;
   }
}