我在运行时使用Strategy Pattern和Abstract Factory Pattern在Calculator类中生成不同的算法。如何将基于泛型迭代器的算法与基于实现的算法结合起来?
计算将取决于相关类型之间的关系。这就是为什么我将“*算法::计算”作为成员函数模板的原因,对于关系来说是通用的。
但是,我已经有一个完全基于实现的算法在现有的代码中,它不是通用的,也不是基于迭代器的,我想将它添加到算法层次结构中,以便我可以使用也可以查看AbstractFactory的行为。
基于实现的算法使用计算中涉及的类型的成员函数来完成计算。在这个例子中,它将使用RelationshipWithA :: target_type成员函数来访问类型&的数据,以及“A”成员函数来访问RelationshipWithA :: a_的数据。
这是我想出了这么远(这只是一个模型,没有抽象工厂,以及计算器类):
#include <iostream>
class Result{};
class A {};
class B {
public:
void specific() const
{
std::cout << "B::specific()" << std::endl;
};
};
class C : public B {};
class D {};
template<class Type>
class RelationshipWithA
{
const A& a_;
const Type& t_;
public:
typedef Type target_type;
RelationshipWithA (const A& a, const Type& t)
:
a_(a),
t_(t)
{
std::cout << "RelationshipWithA::ctor" << std::endl;
};
const A& a() const
{
return a_;
}
const Type& type() const
{
return t_;
}
};
class DefaultAlgorithm
{
public:
template <class Relationship>
void calculate (Result& res, const Relationship& r)
{
std::cout << "DefaultAlgorithm::calculate" << std::endl;
const A& a = r.a();
const typename Relationship::target_type& t = r.type();
// Default iterator based calculation on a, target_type and r
};
};
class AlternativeAlgorithm
:
public DefaultAlgorithm
{
public:
template <class Relationship>
void calculate (Result& res, const Relationship& r)
{
std::cout << "AlternativeAlgorithm::calculate" << std::endl;
// Optimized iterator based calculation on a, target_type and r
}
};
class ImplementationBasedAlgorithm
:
public DefaultAlgorithm
{
public:
// No specialization: Relationships store
// a const reference to any class that inherits from B
template <class Relationship>
void calculate (Result& res, const Relationship& r)
{
// Use B implementation and the Relationship With A to compute the result
std::cout << "ImplementationBasedAlgorithm::calculate" << std::endl;
const A& a = r.a();
const B& b = r.type();
b.specific();
// Implementation based on B implementation
}
};
int main(int argc, const char *argv[])
{
Result res;
A a;
C c;
RelationshipWithA<C> relationshipAC (a, c);
DefaultAlgorithm defaultAlg;
AlternativeAlgorithm alternativeAlg;
ImplementationBasedAlgorithm implementationAlg;
defaultAlg.calculate(res, relationshipAC);
alternativeAlg.calculate(res, relationshipAC);
implementationAlg.calculate(res,relationshipAC);
D d;
RelationshipWithA<D> relationshipAD (a, d);
defaultAlg.calculate(res, relationshipAD);
alternativeAlg.calculate(res, relationshipAD);
// This fails, as expected
//implementationAlg.calculate(res,relationshipAD);
return 0;
}
我喜欢这个设计,因为算法不是一般类,这使通用抽象工厂在运行时很容易生成它们。
但是,在Effective C++中有一个条目36说:“从不重新定义继承的非虚函数”。我的意思是,非虚函数是实现不变的,它们不应该被一般覆盖,但是:
- 在C++中没有可用的虚拟成员函数模板。
- 如果我在RelationshipWithA和“*算法::计算”上创建一个vritual成员函数的算法类泛型,Factory需要知道Realtionship以生成算法,并且代码严重臭(至少对我而言)。
这就是问题的适当解决方案,即使我重写继承的非虚函数(函数模板)?
对于客户来说,行为之间并没有什么不同:结果在那里,唯一的区别在于它的计算方式。这意味着Is-A关系仍然保持:“*算法::计算”对于客户端来说仍然是实现不变的。
什么是“基于实现的算法”? – 2013-03-02 13:09:47
@CrisStringfellow,就像你在ImplementationBasedAlgorithm中看到的那样,它的实现不使用迭代器,它直接使用B成员函数:“B :: specific()”,这使得该算法只能与RelationshipWithA一起使用,该模板使用继承自B,例如C.但是,我希望算法也可以在不同的类型上工作(例如D),并且由于D不是从B继承的,所以ImplementationBasedAlgorithm将不会编译。实际上,A,B和D是来自不同库的非常复杂的类型(但相似),所以我使用通用算法保存代码。 – tmaric 2013-03-02 13:13:55
@CrisStringFellow事实上,ImplementationBasedAlgorithm不能编译为D是*好*,这是我想要的,唯一的问题是我重写了非虚拟成员函数(模板),所以我需要知道这是否是生产守则的标准做法。 – tmaric 2013-03-02 13:15:34