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 = 3; 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>()...); }