c++11 boost技术交流群:296561497,欢迎大家来交流技术。

本次要讲的时候如何改进代理模式,具体来说是动态代理模式,动态代理模式一般实现AOP框架,不懂AOP的童鞋看这里。我前面的博文也实现了一个AOP框架(可以参考我前面的博文:(原创) C++ 轻量级AOP框架),但是那个AOP框架存在一个缺陷,就是不支持切面的组合,这一点大大降低了其通用性,本次通过c++11改进,使AOP框架更完善:支持切面组合,不要求切面必须派生于某个基类,不用虚函数调用,性能更好,功能更强大。

上代码:

struct Aspect : boost::noncopyable
{
template<typename Func>
Aspect(const Func& f) : m_func(f)
{ } template<typename T>
void Invoke(T&& value)
{
value.Before();
m_func();
value.After();
} template<typename Head, typename... Tail>
void Invoke(Head&& head, Tail&&... tail)
{
head.Before();
Invoke(std::forward<Tail>(tail)...);
head.After();
} private:
std::function<void()> m_func;
}; template<typename... AP>
void Invoke(const std::function<void ()>& f)
{
Aspect msp(f);
msp.Invoke(AP()...);
}

切面有要求,切面类中必须要有Before/After方法,否则编译不过,允许空实现。

测试代码:

struct AA
{
void Before()
{
cout<<"Before from AA"<<endl;
} void After()
{
cout<<"After from AA"<<endl;
}
}; struct BB
{
void Before()
{
cout<<"Before from BB"<<endl;
} void After()
{
cout<<"After from BB"<<endl;
}
}; struct CC
{
void Before()
{
cout<<"Before from CC"<<endl;
} void After()
{
cout<<"After from CC"<<endl;
}
}; struct TT
{
void g()
{
cout<<"real g function"<<endl;
} void h(int a)
{
cout<<"real h function: "<<a<<endl;
}
}; struct DD
{
void Before()
{ } void After()
{ }
}; void GT()
{
cout<<"real GT function"<<endl;
} void HT(int a)
{
cout<<"real HT function: "<<a<<endl;
} void TestAOP()
{
TT tt;
std::function<void()> ff = std::bind(&TT::g, &tt);
//组合了两个切面AA BB
Invoke<AA,BB>([&ff](){ff();}); //织入成员函数
Invoke<AA,BB>([&tt](){tt.g();}); //织入对象 int aa = ;
Invoke<AA,BB>(&GT); //织入方法
Invoke<AA,BB>([aa](){HT(aa);});//织入带参的方法 //织入带参数的成员函数和对象
std::function<void(int)> ff1 = std::bind(&TT::h, &tt, std::placeholders::_1);
Invoke<AA,BB,CC,DD>([&ff1,aa](){ff1(aa);}); //组合了四个切面
Invoke<AA,BB>([&tt,aa](){tt.h(aa);});
}

测试结果:

更新:代码在GCC下编译没问题,但在vs2013下编译不过,是微软的bug,如果要在vs2013下编译通过,需要做一点修改:

template<typename T> using identity_t = T;

template<typename... AP>
void Invoke(const std::function<void()>& f)
{
Aspect msp(f);
msp.Invoke(identity_t<AP>()...);
}

(原创)c++11改进我们的模式之改进代理模式,实现通用的AOP框架的更多相关文章

  1. JAVA代理模式与动态代理模式

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某 ...

  2. NET设计模式 第二部分 结构性模式(13):代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) ——.NET设计模式系列之十四 Terrylee,2006年5月 摘要:在软件系统中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另一个对 ...

  3. 《JAVA与模式》之代理模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述代理(Proxy)模式的: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式的结 ...

  4. [19/04/25-星期四] GOF23_结构型模式(适配器模式、代理模式)

    一.引言 结构模式:核心作用就是从程序的结构上实现松耦合,从而扩大整体的类结构,用来解决更大的问题. 二.适配器模式(adapter) 生活中假设笔记本是标准的USB接口但是外置键盘是圆形接口,这时候 ...

  5. 模式的秘密-代理模式(2)-JDK动态代理

    代理模式-动态代理 (1) (2) 代码实践动态代理: 第一步:被代理类的接口: package com.JdkProxy; public interface Moveable { void move ...

  6. 【设计模式】 模式PK:代理模式VS装饰模式

    1.概述 对于两个模式,首先要说的是,装饰模式就是代理模式的一个特殊应用,两者的共同点是都具有相同的接口,不同点则是代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能 ...

  7. Java常见23中设计模式之【代理模式】

    一.静态代理模式 静态代理,使用继承的方式实现自己新增的服务 这种模式可以实现帮助被代理者完成一些前期的准备工作和后期的善后工作,但是核心的业务逻辑仍然是由被代理者完成. 在某些情况下,一个客户不想或 ...

  8. 【编程思想】【设计模式】【结构模式Structural】代理模式Proxy

    Python版 https://github.com/faif/python-patterns/blob/master/structural/proxy.py #!/usr/bin/env pytho ...

  9. java设计模式-----11、代理模式

    Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问. 所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代 ...

随机推荐

  1. 【php】分享一个php转换微信、QQ、微博 特殊非主流 | 杀马特 网名的 function

    1.实现的效果: 2.将上面带有图标.非主流的文字,转换成utf-8格式,能存进去和读出来. 3.code: function emoji_encode($nickname){ $strEncode ...

  2. kubectl top查看k8s pod的cpu , memory使用率情况

    To see the pods that use the most cpu and memory you can use the kubectl top command but it doesn’t ...

  3. libpcap详解【转】

    libpcap详解 2010-12-01 22:07 libpcap(Packet Capture Library),即数据包捕获函数库,是Unix/Linux平台下的网络数据包捕获函数库.它是一个独 ...

  4. 信号之sigsetjmp和siglongjmp函数(转)

    在信号处理程序中经常调用longjmp函数以返回到程序的主循环中,而不是从该处理程序返回. 但是,调用longjmp有一个问题.当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被自动地加到进程的信号 ...

  5. webpack window 安装loader

    1.安装loadernpm install css-loader style-loader --save-dev 2.配置loader,在webpack.config.js中 module: { lo ...

  6. 【Spring】SpringMVC之上传文件

    这里笔者介绍利用SpringMVC上传图片的操作. 步骤 1.  引入jar文件 不仅需要导入开发SpringMVC相关的包,还需要导入 commons-fileupload-1.2.1.jar 和  ...

  7. 【struts2】<s:url>标签

    <s:url>标签一般和超链接 <a>一起使用,用于带多个参数. <a href=" <s:url action=""> < ...

  8. xtrabackup-增量备份

    增量备份之所以能工作是因为每个innodb的page都包含日志序列号(LSN).LSN是整个数据库的版本号. 增量备份会拷贝那些LSN比备份开始时新的页.有两种算法用来计算查找这些页:第一种,支持所有 ...

  9. Linux共享内存使用常见陷阱与分析

    所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式.是针对其他通信机制运行效率较低而设计的.往往与其它通信机制,如 信号量结合使用,来达到进程间的同步及互斥.其他进程能把同一段 ...

  10. unity, 2d rope

    https://www.youtube.com/watch?v=l6awvCT29yU