【发布时间】:2019-05-22 14:42:23
【问题描述】:
我正在开发一个大型软件,该软件严重依赖调用超级反模式。
基本上,接口定义了一个init() 虚拟方法,然后在继承它的每个类中重写该方法。
当在类上调用 init() 时,每个重载的 init 方法都会级联,从基类到顶级子类,以及介于两者之间。
但用户必须自己调用其直接父级的init() 方法,导致代码如下:
class myClass : public Base
{
virtual void init()
{
Parent::Init() // often forgotten, or misplaced by the developer
// Do some init stuff
}
}
对此的替代方法通常是使用委托。 Base 类在 init 中有一些事情要做,即在 Base 中声明为 final,并将其中的一部分委托给继承类应覆盖的 onInit() 方法。但这并没有像我希望的那样级联对所有父类的调用。
我首先实现的替代方法是委托方法的变体。子类和 Base 都实现了 onInit() 和 init() 方法。
init() 调用Parent::init(),然后调用onInit() 本身,并使用模板元编程和宏自动生成。
onInit() 包含特定于类的代码。
# define DELEGATE(T, Parent) \
void init() override { Parent::init(); T::onInit(); }
struct Base
{
virtual void init() { Base::onInit(); }
virtual void onInit() {}
};
struct A : public Base
{
DELEGATE(A, Base)
void onInit() override { /* MyCustom code for A */ }
};
struct B : public A
{
DELEGATE(B, A)
void onInit() override { /* MyCustom code for B */ }
};
这很好用.. 除了多重继承变得一团糟,即使处理,菱形继承也会导致重复调用的问题。
这让我想知道:我不可能是唯一一个在寻找解决我的问题的设计模式的人,stackoverflow 社区必须知道这一点:)
你有没有遇到过这样的设计模式? 我真的很期待你的想法!
【问题讨论】:
-
我不明白。这实际上不是两次调用派生类的
onInit吗?一次来自Base的init,一次来自DELEGATE宏的扩展。 -
对不起,你是对的。 Base::init() 应该在 onInit() 上调用 Base::onInit() 我修复了我的帖子,对此感到抱歉
-
您可以使用 CRTP,而不是 MACRO(因此可以轻松处理多重继承)。
-
对于重复调用,您可以传递一个
std::set<std::type_index>来有条件地调用onInit。
标签: c++ design-patterns super anti-patterns