C++ 如何装饰函数实现代码最大程度复用

0 前言
Hello,大家好,欢迎来到『自由技艺』的 C++ 系列专题 。代码重用,尽可能避免冗余代码是程序员的一项必备技能,今天就来给大家介绍其中一种:函数装饰器 。在设计模式中,与它对应的是类的装饰器模式,但个人觉得很鸡肋,下回再说吧 。
1 需求来源
现在假设有一个基础功能函数,但是呢,存在各种应用场景,每种场景都需要对这个函数小修小补、或增加一些定制化的功能 。有几种处理方式呢?基类派生?函数重载?建造者模式?都不大合适,而函数装饰器就是一种可参考的手段 。
void test(int a, int b) {std::cout << (a + b) << "n";}void do_previous_work() {std::cout << "do previous works" << "n";}void do_after_work() {std::cout << "do after works" << "n";}template<typename RET, typename... ARGS>std::function<RET(ARGS... args)> decorator(RET(*p_func)(ARGS... args)) {return [&](ARGS... args) -> RET {do_previous_work();test(args...);(*p_func)(args...);do_after_work();};//没有捕获任何变量的Lambda表达式可以转换成与它的调用原型一致的函数指针}int main() {int a = 10;int b = 20;f = test;f(a, b);// 第一次调用 fstd::function<void(int, int)> f;f = decorator(test);f(a, b);// 第二次调用 freturn 0;}输出结果:

C++ 如何装饰函数实现代码最大程度复用

文章插图
 
2 总结
上述代码中有一个基本函数 test,如果需要在 test 之前做某些事情(do_previous_work),在 test 之后也做一些事情(do_after_work),那么定义一个装饰器函数,把 test 封装下,再用函数对象接收就可以了 。从结果上看,调用了 f 两次,却输出了不同的结果 。如果再有其他需求,类似地再实现一个装饰器函数,同样用 f 接收,再调用,就可以了 。
留个思考题,如果把装饰器函数写成如下形式:
template<typename RET, typename... ARGS>std::function<RET(ARGS... args)> decorator(RET(*p_func)(ARGS... args)) {auto post = [&](ARGS... args) -> RET {do_previous_work();test(args...);(*p_func)(args...);do_after_work();};return post;}这种写法有什么问题吗?欢迎留言区讨论~

【C++ 如何装饰函数实现代码最大程度复用】


    推荐阅读