用部分通用的实现设计C++类

Designing C++ classes with partly common implementations

本文关键字:C++ 实现 用部      更新时间:2023-10-16

我正在设计一个C++模块。该模块可以接收3种不同类型的请求:请求-A、请求-B和请求-C
对于每种类型,我都有一个相应的处理程序类:RequestHandler-a、RequestHandler-B和RequestHandler-C(所有这些都实现了IRequestHandler接口)
每个处理程序都必须执行某些操作来满足其请求
例如,RequestHandler-A需要按顺序执行这些操作:
行动-1
动作-2
行动-3
行动-4
行动-5

RequestHandler-B需要按顺序执行这些操作:
行动-1
行动-3
行动-5

RequestHandler-C需要按顺序执行这些操作:
行动-4
行动-5

一个操作的结果将被下一个操作使用。

我正在努力设计这些类,以便在处理程序中重用常见的操作实现。有什么设计模式可以在这里应用吗?也许模板方法模式可能是一种可能性,但我不确定。如有任何建议,我们将不胜感激。

PS:为了让事情变得更有趣,还有一个要求,如果Action-2失败,我们应该用不同的数据重试。但也许我想得太远了。

"公共实现"意味着您的解决方案与继承无关。继承是为了接口的重用,而不是实现重用。

你发现你有共同的代码,只是使用共享的功能:

void action1();
void action2();
void action3();
void action4();
void action5();
struct RequestHandlerA : IRequestHandler {
    virtual void handle( Request *r ) {
        action1();
        action2();
        action3();
    }
};
struct RequestHandlerB : IRequestHandler {
    virtual void handle( Request *r ) {
        action2();
        action3();
        action4();
    }
};
struct RequestHandlerC : IRequestHandler {
    virtual void handle( Request *r ) {
        action3();
        action4();
        action5();
    }
};

假设公共函数只是内部助手,您可能希望使它们成为static(或使用匿名命名空间)以获得内部链接。

你在找这样的东西吗?

#include <iostream>
using namespace std;
class Interface{
    public:
        void exec(){
            //prepare things up
            vExec();
            //check everything is ok
        };
        virtual ~Interface(){}
    protected:
        virtual void vExec() = 0;
        virtual void Action0() = 0;
        virtual void Action1(){}
        void Action2(){}
};
void Interface::Action0(){
}
void Action3(){}
class HandlerA : public Interface{
    protected:
        virtual void vExec(){
            Action0();
            Action1();
            Action3();
        }
        virtual void Action0(){
        }
};
class HandlerB : public Interface{
    protected:
        virtual void vExec(){
            Action0();
            Action1();
            Action2();
            Action3();
        }
        virtual void Action0(){
            Interface::Action0();
        }
};
int main()
{
    Interface* handler = new HandlerA();
    handler->exec();
    HandlerB b;
    b.exec();
    delete handler;
}

正如你所看到的,根据你的需要,动作可以是虚拟成员、非虚拟成员、免费功能或你可能想到的任何东西。

向操作提供不同数据的"附加"功能可以在exec()(如果是通用的)或vExec(如果是特定于处理程序的)中执行。如果你给我们更多的细节,我可以相应地修改这个例子。

此外,您还可以将vExec公开并去掉exec。示例中的一个只是我最喜欢的做法(使接口非虚拟,使虚拟函数非公共)。

您可以有一个基类来实现5个操作,并从中派生处理程序。

如果这些操作彼此之间足够隔离,那么您可能也可以将它们分离为单独的函数或类,并让处理程序调用它们。

您考虑过指挥链设计模式吗?http://en.wikipedia.org/wiki/Command_pattern

这是一种经过时间验证的模式,可以促进处理程序对象和它们接收的请求(命令)之间的松散耦合。

您可以将请求对象转换为命令对象。然后指定每个处理程序可以执行的命令类型。然后,您可以将命令传递给Handlers,如果它们无法处理,则让它们向前传递命令。如果处理程序可以处理该操作,那么该命令将通过其各自的操作进行处理。然后,您可以使用组合将每个逻辑操作作为对象本身驻留在处理程序中。