http://www.cnblogs.com/zhengzengyuan/archive/2009/12/18/1626746.html
一个关于泛型结合多态设计方面的文章。
先看段代码:
class IMaterialCoeff {
public:
virtual void ReadCoeff()=0;
};
class DenModelCoeff : public IMaterialCoeff {
public:
virtual void ReadCoeff();
virtual void GetModelCoeffByMaterialNo(const int, vector<ShcCoeffData>& result);
};
class HccModelCoeff : public IMaterialCoeff {
public:
virtual void ReadCoeff();
virtual void GetModelCoeffByMaterialNo(const int, vector<HccCoeffData>& result);
};
.....还有几个类似的继承方式。
在这个例子中IMaterialCoeff是一个抽象的接口,对于设计这个接口的目的有以下两个原因:
1):项目的后期读取系数的方式有可能会改变,所以设计了一个纯虚函数ReadCoeff()来应对以后的变化。
2):减少MaterialCoeff与其他模块之间的耦合性。
但是目前的实现的接口无法满足我的第二点要求。因为在其他模块中更频繁被使用的是派生类中GetModelCoeffByMaterialNo操作。实质上说接口并没有为降低耦合性提供帮助,甚至由于耦合性没有得到降低导致我的第一个实现目标都无法实现。
为什么第二个目的无法实现?很显然是GetModelCoeffByMaterialNo方法具有一个不同类型的参数。导致无法将这个方法抽象到接口中,而影响整个程序的设计和思路的展开。那么怎么样才能构建一个可变化的类型?第一个在我脑海中浮现的就是泛型(template),将接口设计成泛型。出于这个大胆的想法,我写了一段测试程序:
tempalte <typename T>
class Test {
public:
virtual void Func(T & result) = 0; // 将泛型和纯虚函数结合在一起
};
class TestImpl : public Test<int> {
public:
virtual void Func(int& result) { result = 10; std::cout << "TestImpl::Func() Called!" << std::endl; }
};
int main() {
Test *test = new TestImpl;
int result;
test->Func(result);
return 0;
}
很顺利,程序立刻就能顺利的运行,并得到输出: TestImpl::Func() Called,派生类的成员函数通过多态的形式被调用了^_^。说明这种通过模板实现的接口是可行的而且非常的perfect。它仿佛能帮我们实现一个类型可变的多态。接下来,实现工作中的程序,完成下面的设计和代码。
通过模板参数列表类型延迟到模板id确定,实现一种类型可变化的多态假象。而使用泛型设计,实质上我们从上面的UML图可以看出,其实是在派生类和接口之间构建了一道桥梁,来重新衔接出一种继承方式,从而隔离了接口和派生类。OK,现在让我们看看写出来的代码吧。
template <typename Result>
class IMaterialCoeff {
public:
typedef Result result_type;
virtual void ReadCoeff() = 0;
virtual void GetModelCoeffByMaterialNo(const int, Result&) = 0;
};
class ShcModelCoeff :
public IMaterialCoeff<std::vector<ShcCoeffData> > {
public:
virtual void ReadCoeff();
virtual void GetModelCoeffByMaterialNo(const int, result_type& result);
};
class HccModelCoeff :
public IMaterialCoeff<std::vector<HccCoeffData> > {
public:
virtual void ReadCoeff();
virtual void GetModelCoeffByMaterialNo(const int, result_type& result);
};
OK,到目前为止,已经能成功的实现我项目的功能了。
最后,来点总结吧。
1):通过将泛型+多态结合,实现了一种虚函数参数类型可变化的多态。使得我们面临变化多端的程序,有能更好的灵活性。
2):编写程序的时候,要多发现变化之处,思考变化之处,怎么使变化的之处保持不变,最后以不变应万变。就好比上面看到GetModelCoeffByMaterialNo参数是变化的,才知道怎么让其不变。
3):泛型+多态真的很perfect。
好吧!今天就聊到这。