OOP中,Template Method模式的一个典型实现如下:classAbstractTestCase
{
public:
AbstractTestCase(std::stringconst& testName)
: testName_(testName)
{}
voidRunTest()
{
Logger::Instance().Log("Start Test: "+ testName_);
try
{
RunTestImpl();
}
catch(std::exception& e)
{
Logger::Instance().Log("Exception: "+ e.what());
}
catch(...)
{
Logger::Instance().Log("Unknown Exception");
}
Logger::Instance().Log("End Test: "+ testName_);
}
private:
std::string testName_;
virtual voidRunTestImpl() = 0;
};classConcreteTestCase1 :publicAbstractTestCase
{
public:
ConcreteTestCase1()
: AbstractTestCase("ConcreteTestCase1")
{}
private:
virtual voidRunTestImpl()
{
...
}
}...// other ConcreteTestCase that derives from AbstractTestCaseintmain()
{
std::vector
testCases.push_back(
testCases.push_back(newConcreteTestCase2);
...
for(inti=0; i
\testCases[i]->RunTest();
}
return0;
}以上是一个简单的测试框架。其中Logger是一个Singleton对象,它把测试过程中收集的信息写入日志,以便日后分析。RunTest()和RunTestImpl()是Template Method的实作,所有的ConcreteTestCase复用了RunTest()的流程。C++的Template Function也可以实现流程的复用,于是上述代码可以改写为:template<typenameFunction>voidRunTest(std::stringconst&testName, Function test)
{
Logger::Instance().Log("Start Test: "+ testName);
try
{
test();
}
catch(std::exception& e)
{
Logger::Instance().Log("Exception: "+ e.what());
}
catch(...)
{
Logger::Instance().Log("Unknown Exception");
}
Logger::Instance().Log("End Test: "+ testName);
}voidtest1(){...
}voidtest2(){...}intmain()
{
RunTest("test1", test1);RunTest("test2", test2);
return0;
}这个例子只是想说明,如果不需要OOP的动态接口复用,只需要静态代码复用,那么Template Function是一种很方便的选择。此外,配合使用Boost.Bind(它将成为C++09标准库的一部分),我们可以获得额外的弹性。例如,您的TestCase希望从数据文件中读取测试数据,这将有利于您逐步完善测试数据。此外,您也不愿意把测试数据文件的路径写死在测试代码中,这样您可以在不同的时刻使用不同的测试数据集。这时,您可以这样构建您的测试程序。#include"boost/bind.hpp"...voidtestWithFile(char const filePath){...}intmain(intargc,char argv[])
{
// Smoking tests that should be run every timeRunTest("test1", test1);RunTest("test2", test2);if(2 == argc){// Load test file whose path is in argv[1]RunTest("testWithFile", boost::bind(testWithFile, argv[1]));}
return0;
}实际上,利用Boost.Function(它也将成为C++09标准库的一部分),我们甚至可以将RunTest()重构为普通函数(Refactor Template Function to Trivial Function with Generic Delegate)。#include"boost/bind.hpp"#include"boost/function.hpp"voidRunTest(std::string const& testName,boost::function0<void>const&test)
{
Logger::Instance().Log("Start Test: "+ testName);
try
{
test();
}
catch(std::exception& e)
{
Logger::Instance().Log("Exception: "+ e.what());
}
catch(...)
{
Logger::Instance().Log("Unknown Exception");
}
Logger::Instance().Log("End Test: "+ testName);
}...intmain(intargc,char* argv[])
{
// Smoking tests that should be run every timeRunTest("test1", test1);RunTest("test2", test2);if(2 == argc){// Load test file whose path is in argv[1]RunTest("testWithFile", boost::bind(testWithFile, argv[1]));}
return0;
}这个简单的例子表明,C++ Template Metaprogramming将通过程序库来影响我们的编程方式。原文链接: https://www.cnblogs.com/liangshi/archive/2010/04/28/1722860.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/10464
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!