我有一堆算法和集合,并且我正在使用基于策略的设计(参见Modern C++ Design一书)来处理任意组合复杂性。这很好,但是为了防止使用指向策略的指针破坏 Host 类,1建议将策略的析构函数设为受保护。但是,如果我使算法和集合析构函数受到保护,我不能单独使用它们,而只能作为策略使用。此外,与通用工厂模式相比,我没有看到基于策略的设计的好处......
这是代码的模型:
#include <iostream>
template<class Collection>
class AlgorithmOne
{
public:
void doSomethingWithData(Collection& data)
{
// Use Collection iterators to build up an algorithm.
}
};
template<class Collection>
class AlgorithmTwo
{
public:
void doSomethingWithData(Collection& data)
{
// Use Collection iterators to build up an algorithm.
}
};
template<class Collection>
class AlgorithmThree
{
public:
void doSomethingWithData(Collection& data)
{
// Use Collection iterators to build up an algorithm.
}
};
template<class Element>
class CollectionOne
{
public:
typedef Element ElementType;
};
template<class Element>
class CollectionTwo
{
public:
typedef Element ElementType;
};
template<class Element>
class CollectionThree
{
public:
typedef Element ElementType;
};
template<typename HostTraits>
class HostInheritsData
:
public HostTraits::Collection,
public HostTraits::Algorithm
{
public:
typedef HostTraits Traits;
using Traits::Algorithm::doSomethingWithData;
void doSomethingWithData()
{
doSomethingWithData(*this);
}
};
template<typename HostTraits>
class HostCompositsData
:
public HostTraits::Algorithm
{
typename HostTraits::Collection data_;
public:
typedef HostTraits Traits;
using Traits::Algorithm::doSomethingWithData;
void doSomethingWithData()
{
doSomethingWithData(data_);
}
// Clumsy and breaking encapsulation
typename HostTraits::Collection& data()
{
return data_;
}
};
template<typename HostTraits>
class GenericStrategy
{
typename HostTraits::Collection data_;
typename HostTraits::Algorithm algorithm_;
public:
void doSomethingWithData()
{
algorithm_.doSomethingWithData(data_);
}
};
class ElementOne {};
class ElementTwo {};
class ElementThree {};
struct MyConfig
{
typedef ElementOne Element;
typedef CollectionThree<Element> Collection;
typedef AlgorithmOne<Collection> Algorithm;
};
int main(int argc, const char *argv[])
{
HostInheritsData<MyConfig> hostInherits;
hostInherits.doSomethingWithData();
// This must be a mistake, are policies meant to be used this way?
hostInherits.doSomethingWithData(hostInherits);
HostCompositsData<MyConfig> hostComposits;
hostComposits.doSomethingWithData();
// Clumsy to use, not intuitive and breaking encapsulation.
hostComposits.doSomethingWithData(hostComposits.data());
// Combinatorics are there, I can combine whatever I want in MyConfig as for
// policies, but I can also have global Algorithm and Collection objects
// (no protected destructors).
GenericStrategy<MyConfig> strategy;
strategy.doSomethingWithData();
return 0;
}
以下是我的问题:
我正在使用策略自定义一个 Host 类的结构,当每个现实的算法都需要一个 Collection 来工作,而 Collection 被封装在 host 中时,如何才能真正丰富 Host 类的接口?
当我将基于策略的设计与通用工厂进行比较时,通用工厂不会给我带来相同的组合复杂性吗?似乎使用通用工厂更好,因为我也可以在所有可能的组合中交换元素、容器和算法,并且我仍然可以为所有策略拥有公共析构函数,这允许我以任何我想要的方式组合它们,例如元素、集合和算法的全局组合。
在我看来,一旦结构被定制,丰富的策略就会成为一个问题。即使我稍后将成员函数添加到算法中,它也可能具有与 Collection 相关的参数(例如 Collection 迭代器):如果 Host 使用组合封装 Collection,我需要向它询问自己的成员函数的参数:
// Clumsy to use, not intuitive and breaking encapsulation.
hostComposits.doSomethingWithData(hostComposits.data());
如果主机使用继承封装集合,它(至少对我来说)变得更加奇怪:
// This must be a mistake, are policies meant to be used this way?
hostInherits.doSomethingWithData(hostInherits);
我是否完全误解了基于策略的设计(再次),我是否正确使用了这些特征?在这种情况下,通用策略模式是更好的选择吗?