(原创)c++11改进我们的模式之改进代理模式,实现通用的AOP框架
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>(>); //织入方法
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框架的更多相关文章
- JAVA代理模式与动态代理模式
1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某 ...
- NET设计模式 第二部分 结构性模式(13):代理模式(Proxy Pattern)
代理模式(Proxy Pattern) ——.NET设计模式系列之十四 Terrylee,2006年5月 摘要:在软件系统中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另一个对 ...
- 《JAVA与模式》之代理模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述代理(Proxy)模式的: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式的结 ...
- [19/04/25-星期四] GOF23_结构型模式(适配器模式、代理模式)
一.引言 结构模式:核心作用就是从程序的结构上实现松耦合,从而扩大整体的类结构,用来解决更大的问题. 二.适配器模式(adapter) 生活中假设笔记本是标准的USB接口但是外置键盘是圆形接口,这时候 ...
- 模式的秘密-代理模式(2)-JDK动态代理
代理模式-动态代理 (1) (2) 代码实践动态代理: 第一步:被代理类的接口: package com.JdkProxy; public interface Moveable { void move ...
- 【设计模式】 模式PK:代理模式VS装饰模式
1.概述 对于两个模式,首先要说的是,装饰模式就是代理模式的一个特殊应用,两者的共同点是都具有相同的接口,不同点则是代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能 ...
- Java常见23中设计模式之【代理模式】
一.静态代理模式 静态代理,使用继承的方式实现自己新增的服务 这种模式可以实现帮助被代理者完成一些前期的准备工作和后期的善后工作,但是核心的业务逻辑仍然是由被代理者完成. 在某些情况下,一个客户不想或 ...
- 【编程思想】【设计模式】【结构模式Structural】代理模式Proxy
Python版 https://github.com/faif/python-patterns/blob/master/structural/proxy.py #!/usr/bin/env pytho ...
- java设计模式-----11、代理模式
Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问. 所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代 ...
随机推荐
- 【PHP5.3+】获取getCurrentUrl()中 的地址url
1.在控制器中调用其他 扩展或者类 的方法时候,getCurrentUrl()方法 是获取的[当前控制器下方法]的路由,不是[其他 扩展或者类 方法]的路由!!! 2.getCurrentUrl()方 ...
- MyEclipse 2014安装properties文件插件
安装步骤 1.下载PropertiesEditor插件 http://propedit.sourceforge.jp/index_en.html2.解压出features.plugins文件3.在My ...
- log4delphi使用(转)
转自:http://blog.csdn.net/brightgems/article/details/814042 Log4d是apache下的一个delphi开源子项目,它的设计思想来源于Log4j ...
- 使用import简化spring的配置 spring import 标签的解析 使用import或加载spring配置时,报错误There is no ID/IDREF 多个Spring配置文件import resource路径配置
spring-import 标签的解析.使用案例: 对于spring配置文件的编写,我想,对于经历过庞大项目的人,都有那种恐惧的心理,太多的配置文件.不过,分模块都是大多数人能想到的方法,但是,怎么分 ...
- IT技术需求建立时需考虑的因素
2012-11-13 内容存档在evernote,笔记名"IT技术需求建立时需考虑的因素"
- POJ 1637 Sightseeing tour (SAP | Dinic 混合欧拉图的判断)
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6448 Accepted: 2654 ...
- kubelet源码分析(version: git tag 1.7.6)
一.概述 kubelet源码入口:cmd/kubelet/kubelet.go main() cmd/kubelet/app 包中的Run函数: 查看先参数,kubelet.KubeletDeps t ...
- Centos 安装GIT 1.7.1
在Linux上安装Git 1.首先,你可以试着输入git,看看系统有没有安装Git: git 2.安装GIT https://git-scm.com/download/linux yum instal ...
- flume+elasticsearch+kibana遇到的坑
在elasticsearch中存储数据的行为就叫做索引(indexing),不过在索引之前,我们需要明确数据应该存储在哪里. 在elasticsearch中,文档归属于一种类型(type),而这些类型 ...
- AndroidStudio编译错误:Error: null value in entry: blameLogFolder=null
今天写项目的时候,电脑开了个WiFi热点,然后这个热点和window驱动不兼容,有时候会导致电脑重启,重启之后AndroidStudio编译就报错了, Error: null value in ent ...