对于基于策略的类设计,我需要一些策略来调用在其他策略中找到的函数:
struct PolicyA {
void foo() {
// ...
}
};
struct PolicyB {
void bar() {
// Need to call foo() here
}
};
template <class A, class B> MyClass : A, B {};
我看到的两个选项是:
- 将
MyClass
传递给 PolicyA
和 PolicyB
作为模板参数,并执行类似 dynamic_cast*>(this)->foo();
的操作。然而,这很容易变得非常复杂(特别是如果不仅 B
调用 A
而且还有其他方式)。
- 每个策略都有一个基类,其中所有函数都声明为纯虚函数。当函数之一需要自己的模板参数时,此操作会失败,因为虚拟模板函数是不可能的。
这应该是一个常见问题,但我没有发现任何问题。我猜想可能有某种增强魔法之类的东西。你会如何解决这个问题?
编辑:另请参阅此处的后续内容。
For a policy-based class-design I need some of the policies to call functions that are found in other policies:
struct PolicyA {
void foo() {
// ...
}
};
struct PolicyB {
void bar() {
// Need to call foo() here
}
};
template <class A, class B> MyClass : A, B {};
The two options I see are:
- Pass
MyClass<A, B>
to PolicyA
and PolicyB
as template parameters and do something like dynamic_cast<MyClass<A, B>*>(this)->foo();
. However this may easily get very complicated (especially if it's not only B
calling A
but also the other way).
- Have a base class for each policy where all the functions are declared as pure virtual. This fails when one of the function needs its own template parameters, since virtual template functions are not possible.
This should be a common problem, but I didn't find anything. I guess there probably is some boost-magic or something. How would you solve this?
Edit: See also the followup here.
发布评论
评论(1)
为什么
PolicyB
不封装PolicyA
并根据需要调用它?PolicyB
显然知道PolicyA
- 不需要基类或继承。似乎您的所有
Policy
实现都有一些外部调用者可以同意的通用apply
方法?编辑:
是的,所以如果这不仅仅是一个特定策略实现需要访问另一个策略实现的简单情况,您可能应该专注于为
Policy
创建一个接口 - 甚至可能一个Rule
类,可以组合在一起形成特定的Policy
- 请参阅规范模式。随意称呼它们,
Condition
、Rule
、Specification
- 它们对于以一种不需要的方式将逻辑片段组装在一起很有用。依赖他们。然后,当有人查看 PolicyA 时,他们可以清楚地看到控制其行为的规则/条件(客观化)。一旦您实现了策略,如果您需要对某些内容强制执行多个策略,您可以再次使用复合模式,以便外部类只能看到
Policy
接口。但同样,您有一个明确的“命名”策略被引用,而不仅仅是交叉调用函数。Why doesn't
PolicyB
encapsulatePolicyA
and call it as it needs?PolicyB
is obviously aware ofPolicyA
- no need for base classes or inheritance.It seems like all of your
Policy
implementations have some commonapply
method that outside callers can agree upon?Edit:
Right, so if it's not just a simple case of one particular Policy implementation needing access to another, you should probably focus on creating a single interface for
Policy
- perhaps even aRule
class that can be composed together to form a particularPolicy
- see the Specification pattern.Call them whatever you want,
Condition
,Rule
,Specification
- they're useful for assembling pieces of logic together in a manner that doesn't depend on them. Then when someone is looking at PolicyA they can see, clearly, the rules/conditions that govern its behavior, objectified.Once you have policy implementations in place, if you need to enforce several policies on something, you can use the composite pattern again so that external classes only see a
Policy
interface. But again, you have a clear 'named' policies that are being referred to, not just cross-calling functions.