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. Oracle11gR2

    oracel目前企业用的最多的数据库,源码包值得下载 点击下载 安装引用: http://blog.csdn.net/cafardhaibin/article/details/25071249 htt ...

  2. flex水平垂直居中

    <div class="parent"> <div class="children">我是通过flex的水平垂直居中噢!</div ...

  3. PendingIntent传递数据注意参数RequestCode和Flag

    数据发送方: public static void notify(Context context, TxrjMessage msg) {     NotificationManager notifiM ...

  4. 关于js中的回调函数callback

    来源于:http://www.jianshu.com/p/6bc353e5f7a3 前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制 ...

  5. Quartz中时间表达式的设置-----corn表达式 (转)

    Quartz中时间表达式的设置-----corn表达式 (注:这是让我看比较明白的一个博文,但是抱歉,没有找到原作者,如有侵犯,请告知) 时间格式: <!-- s m h d m w(?) y( ...

  6. 个人常用eclipse快捷键,不定期更新

    ctrl+f11 ==> runctrl+h ==> 全文检索main+enter ==>public static void main(String[] args) { } alt ...

  7. ubuntu下制作u盘启动盘

    ubuntu12.04下成功制作了ubuntu13.10 U盘启动盘. 成功 ubuntu14.04下成功制作了centos.7 U盘启动盘.成功 1.安装u盘制作工具unetbootin sudo ...

  8. Socket模型(二):完成端口(IOCP)

    为什么要采用Socket模型,而不直接使用Socket? 原因源于recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他链接不能继续.这样我们又 ...

  9. 【Android】详解Android动画

    目录结构: contents structure [+] 补间动画 使用java代码实现Alpha.Rotate.Scale.Translate动画 通过xml文件实现Alpha.Rotate.Sca ...

  10. Postgresql 正则表达式

    在postgresql中使用正则表达式时需要使用关键字“~”,以表示该关键字之前的内容需匹配之后的正则表达式,若匹配规则不需要区分大小写,可以使用组合关键字“~*”: 相反,若需要查询不匹配这则表达式 ...