【发布时间】:2016-11-22 04:27:00
【问题描述】:
假设有一个类 Foo,它使用 F1、F2、F3 函数定义其行为。很少有客户端可以扩展 Foo 的行为并根据需要对其进行自定义。
对于这种情况,直接将其实现为
class Foo
{
public:
virtual void F1() { // default behavior }
virtual void F2() { // default behavior }
virtual void F3() { // default behavior }
}
class CustomFoo1 : public Foo
{
public:
void F1() override { // customized behavior }
void F11() { // CustomFoo1's own methods }
}
class CustomFoo2 : public Foo
{
public:
void F1() override { // customized behavior }
void F21() { // CustomFoo2's own methods }
void F22() { // CustomFoo2's own methods }
}
对吗?但这只有在我的库为其他客户端公开 Class Foo 以创建 CustomFoo1 和 CustomFoo2 时才有可能。我不想公开我的具体实现,而是我会使用其他人可以使用的接口。所以我可以将我的实现更改为:
interface IFoo // Public interface
{
public:
virtual void F1() = 0;
virtual void F2() = 0;
virtual void F3() = 0;
}
Class Foo : public IFoo // Internal to library
{
public:
virtual void F1() override { // default behavior }
virtual void F2() override { // default behavior }
virtual void F3() override { // default behavior }
}
static IFoo* CreateFoo() { return new Foo(); }
class CustomFoo1 : public IFoo
{
public:
void F1() override { // Custom Behavior }
void F2() override { pFoo->F2(); // Need default so delegate call to default implementation }
void F3() override { pFoo->F3(); // Need default so delegate call to default implementation }
void F11() { // personal own implementation }
private:
IFoo* pFoo;
}
CustomFoo2 也是如此。
但是在这里,如果您看到的话,我可以将我的具体实现隐藏在接口后面,但这会导致我的客户实际实现整个接口,并且如果自定义类不想覆盖默认行为中的任何内容,则将调用委托给库中的默认实现.所以我也不认为这是一个好的解决方案。
这让我想到下一个可能的解决方案。如果你仔细看看,图书馆的客户真的在寻找只定制 F1()。 所以我声明另一个接口说 IFooCustomizePolicy
interface IFooCustomizePolicy
{
public:
virtual void F1Customized() = 0;
}
我将 IFoo 修改为:
interface IFoo // Public interface
{
public:
virtual void F1() = 0;
virtual void F2() = 0;
virtual void F3() = 0;
virtual void RegisterCustomizationPolicy(IFooCustomizePolicy* pPolicy) = 0;
}
将具体实现更新为:
Class Foo : public IFoo // Internal to library
{
public:
void F1() override
{
if( pPolicy != nullptr )
pPolicy->F1Customized();
else
// default behavior
}
void F2() override { // default behavior }
void F3() override { // default behavior }
void RegisterCustomizationPolicy(IFooCustomizePolicy* pPolicy) override
{ this->pPolicy = pPolicy; }
private:
IFooCustomizePolicy* pPolicy;
}
而其他客户端会修改为:
class CustomFoo1 : public IFooCustomizePolicy
{
public:
void F1Customized() override { // customized behavior }
void F11() { //CustomFoo1's own methods }
}
现在,如果您看到,通过这种方法,我能够隐藏我的具体类,但能够为客户端提供默认行为以及自定义它的方式。
现在让我们说,需求变化和新客户来了,并要求新的方法是可定制的。在这种情况下,我将不得不更新策略接口,这没关系,这是可以接受的。但除此之外,我需要做的是更新 Foo 的相应方法以尊重策略,并在每次将它们添加到策略时将以下逻辑添加到方法中。
if( policy present ) then call policy customized method
else continue with default behavior
如果你在这里看到,我真正想要的是一种过滤器,如果我的对象有策略,那么过滤器应该调用策略方法并且不应该继续使用默认实现。但我不确定要应用什么模式以及如何应用?
【问题讨论】:
-
我觉得桥接设计模式在这里可以很好地工作,这样接口就可以与实现分离。
标签: c++ design-patterns template-meta-programming