設(shè)計模式之代理模式
掃描二維碼
隨時隨地手機看文章
|
【多數(shù)人都擁有自己不了解的能力和機會,都有可能做到未曾夢想的事情?!鳡枴た突?/p> ——卡耐基 |
前面的文章中程序喵分享過設(shè)計模式中所有的創(chuàng)建型模式,今天開始結(jié)構(gòu)型模式的分享,結(jié)構(gòu)型模式主要總結(jié)了一些類和對象組合的框架,這些框架通常用于解決某些特定場景的問題。 今天開始分享結(jié)構(gòu)型模式的第一個模式:代理模式。
代理模式中通常有三個角色,一個是抽象產(chǎn)品角色,一個是具體產(chǎn)品角色,另一個是代理產(chǎn)品角色,這個代理產(chǎn)品角色的作用是什么呢?引入了代理產(chǎn)品角色是為了給原始的具體產(chǎn)品附加功能。注意這里代理模式附加的是跟原始類無關(guān)的功能,附加的如果是跟原始類有關(guān)的功能那是裝飾器模式,后續(xù)程序喵會介紹。
代碼實現(xiàn)如下:
struct Product {
virtual ~Product() {}
virtual void Use() = 0;
};
struct ConcreteProduct : public Product {
void Use() override { std::cout << "use product\n"; }
};
struct ProductProxy : public Product {
private:
Product *product_;
public:
ProductProxy() { product_ = new ConcreteProduct(); }
~ProductProxy() { delete product_; }
void Use() override {
auto begin_use = [] { std::cout << "use product begin\n"; };
auto end_use = [] { std::cout << "use product end\n"; };
begin_use();
product_->Use();
end_use();
}
};
int main() {
ProductProxy proxy;
proxy.Use();
return 0;
}
上述代碼即使用了代理模式為某個類附加了一些額外的功能,這里為具體產(chǎn)品類使用前后附加了一些log功能,平時開發(fā)過程中如果我們想要為某個類附加一些額外功能時,可以考慮使用代理模式。
C++中的切面編程(AOP)也可以理解為是一種代理模式:
using namespace std;
template <typename T, typename... Args> \
struct has_member_
private: \
template <typename U> \
static auto Check(int) -> decltype(std::declval<U>().member(std::declval<Args>()...), std::true_type()); \
template <typename U> \
static std::false_type Check(...); \
\
public: \
enum { value = std::is_same<decltype(Check<T>(0)), std::true_type>::value }; \
};
HAS_MEMBER(Foo)
HAS_MEMBER(Before)
HAS_MEMBER(After)
template <typename Func, typename... Args>
struct Aspect {
Aspect(Func&& f) : m_func(std::forward<Func>(f)) {}
template <typename T>
typename std::enable_if<has_member_Before<T, Args...>::value && has_member_After<T, Args...>::value>::type Invoke(
Args&&... args, T&& aspect) {
aspect.Before(std::forward<Args>(args)...); //核心邏輯之前的切面邏輯
m_func(std::forward<Args>(args)...); //核心邏輯
aspect.After(std::forward<Args>(args)...); //核心邏輯之后的切面邏輯
}
template <typename T>
typename std::enable_if<has_member_Before<T, Args...>::value && !has_member_After<T, Args...>::value>::type Invoke(
Args&&... args, T&& aspect) {
aspect.Before(std::forward<Args>(args)...); //核心邏輯之前的切面邏輯
m_func(std::forward<Args>(args)...); //核心邏輯
}
template <typename T>
typename std::enable_if<!has_member_Before<T, Args...>::value && has_member_After<T, Args...>::value>::type Invoke(
Args&&... args, T&& aspect) {
m_func(std::forward<Args>(args)...); //核心邏輯
aspect.After(std::forward<Args>(args)...); //核心邏輯之后的切面邏輯
}
template <typename Head, typename... Tail>
void Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect) {
headAspect.Before(std::forward<Args>(args)...);
Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
headAspect.After(std::forward<Args>(args)...);
}
private:
Func m_func; //被織入的函數(shù)
};
template <typename T>
using identity_t = T;
// AOP的輔助函數(shù),簡化調(diào)用
template <typename... AP, typename... Args, typename Func>
void Invoke(Func&& f, Args&&... args) {
Aspect<Func, Args...> asp(std::forward<Func>(f));
asp.Invoke(std::forward<Args>(args)..., identity_t<AP>()...);
}
struct TimeElapsedAspect {
void Before(int i) { m_lastTime = GetTime(); }
void After(int i) { cout << "time used: " << GetTime() - m_lastTime << endl; }
private:
long long m_lastTime;
long long GetTime() {
struct timeval time;
gettimeofday(&time, NULL);
return static_cast<long long>(time.tv_sec * 1000) + static_cast<long long>(time.tv_usec / 1000);
}
};
struct LoggingAspect {
void Before(int i) { std::cout << "begin" << std::endl; }
void After(int i) { std::cout << "end" << std::endl; }
};
void Func(int a) { cout << "Function: " << a << endl; }
int main() {
Invoke<LoggingAspect, TimeElapsedAspect>(&Func, 1); //織入方法
cout << "-----------------------" << endl;
Invoke<TimeElapsedAspect, LoggingAspect>(&Func, 1);
return 0;
}
通過AOP可以為某個函數(shù)前后編織切入一些方法,組成一個新的函數(shù),這里也起到了代理作用,可以理解為一種靜態(tài)代理。
參考資料
https://www.runoob.com/design-pattern/proxy-pattern.html
https://www.cnblogs.com/qicosmos/p/4772389.html
往期推薦
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!