什么是正确的设计方法?

时间:2022-06-01 21:27:26

I have following existing scenario.

我遵循现有的方案。

I have a Validator class containing validate( Command* ) function which validates the Command passed to it.

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

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

}

I have three classes say WindowsExecute, SolarisExecute and AIXExecute. Member function execute() in SolarisExecute and AIXExecute directly create object of Validator and use the validate( Comman* ) function for validating the Command before executing.

我有三个类,比如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 is completely different and does not have any Command. Instead it need to validate some string data. To do this there is a separate class called WindowsValidator inherited from Validator. WindowsExecute::execute() uses WindowsValidator instead of Validator.

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'
   }
}

This is existing code.

这是现有代码。

Now I need to do some specific validations of Solaris and hence can't use Validator::validate( Command* ). Following the current design, I would need to create new class called SolarisValidator and have my own implementation of validate( Command* ).

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

I am not comfortable with this approach. Some issues/comments I think:

我不熟悉这种方法。我认为有些问题/意见:

  1. Validator class would be used only by AIXExecute. Then why have a base class if there is nothing common logic remaining? Simply have three classes SolarisValidator, AIXValidator, WindowsValidator.

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

  2. Validator::validate( Command* ) unnecessarily gets inherited into WindowsValidate class. Note the signature of WindowsValidate::validate(string) and Validator::validate( Command* ) are different.

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

  3. I should make Validator::validate( Command* ) virtual if I introduce SolarisValidator::validate( Command* ). It means I am introducing overhead of virtual pointers even though I am not using any dynamic polymorphism. So why not go with #1 above and create three separate classes?

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

What would be the best solution for this scenario which would also be extensible in future? I am using C++ for implementation.

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

Thanks in advance.

提前致谢。

-GP

2 个解决方案

#1


It looks like you have the concept of a Command, that is valid or not. Depending on your platform, the command is represented in a different form.

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

So I wondered: why not create an ICommand interface with a function "isValid", and have your platform-wrapping code create the proper ICommand object for that platform. This would free your "execute" call from creating a validator, and hence making it platform-independent.

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

Note: this platform-wrapper subsystem is imho best designed using the Factory pattern.

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

#2


It sounds very much like you don't actually have any common functionality or even a common interface between your various ...Validator classes. Personally I would remove the common base class and only resurrect it if a genuine common interface emerges. Trying to force a common base class with no clear purpose or benefit will only lead to messy code and/or a maintenance cost without benefit.

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

At this point you might want to remove the ...Validator classes altogether and move the functionality into a separate function of the ...Execute classes. It sounds as though the validation is tightly bound to the implementation of the execute methods and that this is why you are having difficulty abstracting an appropriate validation interface.

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

Trying to uncouple things which are inherently tightly coupled is frequently an exercise in futility. On the other hand, things which aren't inherently tightly coupled shouldn't be allowed to become tightly coupled in implementation purely through bad design.

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

#1


It looks like you have the concept of a Command, that is valid or not. Depending on your platform, the command is represented in a different form.

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

So I wondered: why not create an ICommand interface with a function "isValid", and have your platform-wrapping code create the proper ICommand object for that platform. This would free your "execute" call from creating a validator, and hence making it platform-independent.

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

Note: this platform-wrapper subsystem is imho best designed using the Factory pattern.

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

#2


It sounds very much like you don't actually have any common functionality or even a common interface between your various ...Validator classes. Personally I would remove the common base class and only resurrect it if a genuine common interface emerges. Trying to force a common base class with no clear purpose or benefit will only lead to messy code and/or a maintenance cost without benefit.

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

At this point you might want to remove the ...Validator classes altogether and move the functionality into a separate function of the ...Execute classes. It sounds as though the validation is tightly bound to the implementation of the execute methods and that this is why you are having difficulty abstracting an appropriate validation interface.

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

Trying to uncouple things which are inherently tightly coupled is frequently an exercise in futility. On the other hand, things which aren't inherently tightly coupled shouldn't be allowed to become tightly coupled in implementation purely through bad design.

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