什么是正确的设计方法?

时间:2009-07-24 09:33:13

标签: c++ inheritance

我有以下现有方案。

我有一个包含validate(Command *)函数的Validator类,它验证传递给它的Command。

class Validator
{
public:
   validate(Command* cmd)
   { 
        // common validation logic
   }

}

我有三个类,比如WindowsExecute,SolarisExecute和AIXExecute。 SolarisExecute中的成员函数execute()和AIXExecute直接创建Validator的对象,并在执行之前使用validate(Comman *)函数验证Command。

class SolarisExecute
{
public:
   execute(Command *cmd)
   {
        Validator v;
        bool valid = v.validate(cmd);

        // some processing depending on 'valid'
   }
}

class AIXExecute
{
public:
   execute(Command *cmd)
   {
        Validator v;
        bool valid = v.validate(cmd);

        // some processing depending on 'valid'
   }
}

WindowsExecute完全不同,没有任何命令。相反,它需要验证一些字符串数据。为此,有一个名为WindowsValidator的独立类继承自Validator。 WindowsExecute :: execute()使用WindowsValidator而不是Validator。

class WindowsValidator : Validator
{
public:
   validate(const string &xmlData)
   {
       // specific validation logic
   }
}

class WindowsExecute
{
public:
   execute(const string &data)
   {
        WindowsValidate v;
        bool valid = v.validate(data);

        // some processing depending on 'valid'
   }
}

这是现有代码。

现在我需要对Solaris进行一些特定的验证,因此不能使用Validator :: validate(Command *)。按照当前的设计,我需要创建一个名为SolarisValidator的新类,并拥有自己的validate(Command *)实现。

我对这种做法不满意。我认为有些问题/意见:

  1. Validator类仅由AIXExecute使用。那么为什么有一个基类,如果没有什么常见的逻辑?只需要三个类SolarisValidator,AIXValidator,WindowsValidator。

  2. Validator :: validate(Command *)不必要地继承到WindowsValidate类中。请注意,WindowsValidate :: validate(字符串)和Validator :: validate(Command *)的签名是不同的。

  3. 如果我引入SolarisValidator :: validate(Command *),我应该使Validator :: validate(Command *)为virtual。这意味着即使我没有使用任何动态多态,我也会引入虚拟指针的开销。那么为什么不选择上面的#1并创建三个单独的类?

  4. 这个场景的最佳解决方案是什么,将来也可以扩展?我正在使用C ++实现。

    提前致谢。

    -GP

2 个答案:

答案 0 :(得分:2)

看起来你有一个命令的概念,有效与否。根据您的平台,命令以不同的形式表示。

所以我想知道:为什么不用函数“isValid”创建一个ICommand接口,并让你的平台包装代码为该平台创建正确的ICommand对象。这将使您的“执行”调用从创建验证器中解放出来,从而使其与平台无关。

注意:这个平台包装子系统是使用工厂模式设计的最好的。

答案 1 :(得分:0)

听起来很像你实际上没有任何常见的功能,甚至你的各种... Validator类之间的通用接口。就个人而言,我会删除公共基类,只有在出现真正的通用接口时才会复活它。试图强制一个没有明确目的或利益的共同基类只会导致代码混乱和/或维护成本而无法获益。

此时您可能想要完全删除... Validator类,并将功能移动到... Execute类的单独函数中。听起来好像验证 与执行方法的实现紧密相关,这就是为什么你难以抽象出适当的验证接口。

试图解开本来紧密耦合的东西往往是徒劳的。另一方面,不应该允许非本质上紧密耦合的东西在纯粹通过糟糕的设计实现紧密耦合。