C++利用代理模式實現(xiàn)遠程代理,虛擬代理和保護代理
一、代理模式基礎(chǔ)介紹
1.1 基礎(chǔ)
C++代理模式是一種結(jié)構(gòu)型設(shè)計模式,其主要目的是為其他對象提供一種代理,以控制對這些對象的訪問。代理對象可以充當原始對象的包裝器,將請求轉(zhuǎn)發(fā)到原始對象,并且可以在轉(zhuǎn)發(fā)請求之前或之后執(zhí)行一些額外的操作。
代理模式通常用于以下幾種情況:
遠程代理:用于在不同地址空間中的兩個對象之間通信,將請求發(fā)送到遠程對象。
虛擬代理:用于延遲加載,即在需要時加載資源。
保護代理:用于控制對對象的訪問權(quán)限,例如,只有特定用戶才能訪問某個對象。
緩存代理:用于緩存對象的訪問結(jié)果,以避免重復執(zhí)行計算密集型操作。
在C++中實現(xiàn)代理模式可以使用抽象類和接口來定義代理和原始對象之間的通信協(xié)議,并使用具體類來實現(xiàn)它們。代理對象將請求轉(zhuǎn)發(fā)給原始對象,并可以在轉(zhuǎn)發(fā)請求之前或之后執(zhí)行一些額外的操作。
1.2 代碼示例
以下是一個簡單的C++代理模式的示例代碼:
#include <iostream>
using namespace std;
// 定義抽象類 Subject,代表原始對象和代理對象共同的接口
class Subject {
public:
virtual void request() = 0;
};
// 定義具體類 RealSubject,實現(xiàn)原始對象的功能
class RealSubject : public Subject {
public:
void request() override {
cout << "RealSubject: Handling request." << endl;
}
};
// 定義代理類 Proxy,實現(xiàn)代理對象的功能
class Proxy : public Subject {
private:
RealSubject* real_subject_;
void check_access() const {
cout << "Proxy: Checking access prior to handling request." << endl;
}
public:
Proxy(RealSubject* real_subject) : real_subject_(real_subject) {}
void request() override {
check_access();
real_subject_->request();
}
};
int main() {
RealSubject* real_subject = new RealSubject;
Proxy* proxy = new Proxy(real_subject);
proxy->request();
delete proxy;
delete real_subject;
return 0;
}在這個示例中,抽象類 Subject 定義了原始對象和代理對象共同的接口 request(),具體類 RealSubject 實現(xiàn)了原始對象的功能,代理類 Proxy 實現(xiàn)了代理對象的功能,并在轉(zhuǎn)發(fā)請求之前執(zhí)行了一個額外的操作 check_access()。在 main() 函數(shù)中,創(chuàng)建了一個 RealSubject 對象和一個 Proxy 對象,并通過 Proxy 對象調(diào)用了 request() 方法。
類圖如下:

二、遠程代理(Remote proxy)
C++遠程代理是一種設(shè)計模式,它允許客戶端通過代理對象間接訪問遠程服務或?qū)ο?。這個模式通常被用于網(wǎng)絡編程中,比如RPC(遠程過程調(diào)用)或分布式系統(tǒng)中。
// 假設(shè)這是遠程服務端對象的頭文件
class RemoteService {
public:
virtual void foo() = 0;
};
// 代理類,用于訪問遠程服務端對象
class RemoteServiceProxy : public RemoteService {
public:
RemoteServiceProxy(const std::string& host, int port) : m_host(host), m_port(port) {}
void foo() override {
// 連接遠程服務端
connect();
// 向遠程服務端發(fā)送請求
sendRequest("foo");
// 等待遠程服務端響應
std::string response = receiveResponse();
// 關(guān)閉連接
disconnect();
// 處理響應
processResponse(response);
}
private:
std::string m_host;
int m_port;
int m_socketFd; // 保存套接字描述符,用于連接遠程服務端
void connect() {
// 連接遠程服務端代碼
}
void sendRequest(const std::string& request) {
// 向遠程服務端發(fā)送請求代碼
}
std::string receiveResponse() {
// 從遠程服務端接收響應代碼
}
void disconnect() {
// 關(guān)閉連接代碼
}
void processResponse(const std::string& response) {
// 處理響應代碼
}
};
// 客戶端代碼
int main() {
RemoteServiceProxy proxy("127.0.0.1", 8080);
proxy.foo(); // 通過代理對象間接訪問遠程服務端對象的foo()方法
return 0;
}上述代碼中,RemoteService是一個抽象基類,它定義了遠程服務端對象的接口。RemoteServiceProxy是代理類,它通過套接字描述符連接遠程服務端,并將客戶端的請求轉(zhuǎn)發(fā)給遠程服務端??蛻舳酥恍枰ㄟ^代理對象訪問遠程服務端的方法即可,而無需知道遠程服務端的具體實現(xiàn)細節(jié)。
類圖如下:

三、虛擬代理(Virtual Proxy)
C++虛擬代理(Virtual Proxy)模式是一種結(jié)構(gòu)型設(shè)計模式,它允許你創(chuàng)建一個代理對象來代替一個真實對象。該代理對象可以控制對真實對象的訪問,并在需要時才創(chuàng)建或加載真實對象。
代碼示例:
#include <iostream>
using namespace std;
// 定義一個抽象類Subject
class Subject {
public:
virtual void request() = 0;
};
// 定義一個真實的Subject類RealSubject
class RealSubject : public Subject {
public:
void request() {
cout << "真實的請求" << endl;
}
};
// 定義一個代理類Proxy
class Proxy : public Subject {
private:
RealSubject *realSubject;
public:
void request() {
if (realSubject == nullptr) {
realSubject = new RealSubject();
}
cout << "代理請求" << endl;
realSubject->request();
}
};
// 客戶端代碼
int main() {
Proxy proxy;
proxy.request();
return 0;
}在上面的示例中,我們定義了一個抽象類Subject和一個具體的類RealSubject,它們都實現(xiàn)了request()方法。然后我們定義了一個代理類Proxy,它也實現(xiàn)了request()方法,但是它首先檢查真實的主題是否已經(jīng)創(chuàng)建,如果沒有創(chuàng)建,則創(chuàng)建一個。然后代理類打印一條消息,表示代理請求。最后,它調(diào)用真實主題的request()方法。
在客戶端代碼中,我們實例化了一個代理對象,并調(diào)用了request()方法。由于我們使用了代理模式,所以當我們調(diào)用代理對象的request()方法時,它將首先創(chuàng)建真實對象(如果沒有創(chuàng)建),然后打印代理請求,最后調(diào)用真實對象的request()方法。
這種模式的一個好處是,它可以延遲創(chuàng)建真實對象的時間,直到它真正需要使用。這可以節(jié)省資源,特別是當創(chuàng)建真實對象的代價很大時。
類圖:

四、保護代理(Protective Proxy)
C++中的保護代理(Protective Proxy)是一種結(jié)構(gòu)型設(shè)計模式,其目的是控制對對象的訪問。它使用一個代理對象來控制原始對象的訪問,代理對象通過限制或控制原始對象的訪問來提供額外的安全性和保護。
#include <iostream>
#include <string>
#include <memory>
class Image {
public:
Image(std::string name) : name_(name) {}
virtual void Display() = 0;
virtual ~Image() {}
protected:
std::string name_;
};
class RealImage : public Image {
public:
RealImage(std::string name) : Image(name) {
LoadFromDisk();
}
void Display() override {
std::cout << "Displaying " << name_ << std::endl;
}
private:
void LoadFromDisk() {
std::cout << "Loading " << name_ << " from disk" << std::endl;
}
};
class ImageProxy : public Image {
public:
ImageProxy(std::string name) : Image(name) {}
void Display() override {
if (real_image_ == nullptr) {
real_image_ = std::make_unique<RealImage>(name_);
}
real_image_->Display();
}
private:
std::unique_ptr<RealImage> real_image_;
};
int main() {
// Create a real image object
auto real_image = std::make_unique<RealImage>("image1.jpg");
// Display the real image
real_image->Display();
// Create an image proxy object
auto image_proxy = std::make_unique<ImageProxy>("image2.jpg");
// Display the image proxy
image_proxy->Display();
// The real image is only loaded once, even though it is displayed twice
return 0;
}在上面的示例代碼中,Image 是一個抽象基類,RealImage 和 ImageProxy 是具體的類。RealImage 是一個真實的圖像對象,它可以從磁盤中加載并顯示圖像。ImageProxy 是一個代理對象,它可以訪問真實圖像對象,并負責加載和顯示真實圖像對象。當我們調(diào)用 ImageProxy 對象的 Display() 方法時,它會首先檢查是否已經(jīng)加載了真實圖像對象。如果沒有加載,它將使用 RealImage 對象加載圖像。這種方式可以減少對真實圖像對象的頻繁訪問,從而提高程序的效率。
類圖:

五、緩存代理(Cache Proxy)
緩存代理模式的基本思路是:為了避免每次調(diào)用一個函數(shù)或方法時都要進行重復的計算,我們可以將其結(jié)果緩存起來,下次需要時就可以直接返回緩存的結(jié)果,而不用再進行計算。
#include <iostream>
#include <unordered_map>
using namespace std;
// 定義一個全局的緩存代理類
class FactorialCacheProxy {
public:
int getFactorial(int n) {
if (cache_.find(n) != cache_.end()) {
// 如果結(jié)果已經(jīng)被緩存,直接返回緩存的結(jié)果
cout << "Get result from cache: " << n << endl;
return cache_[n];
} else {
// 如果結(jié)果沒有被緩存,進行計算并緩存結(jié)果
cout << "Calculate result: " << n << endl;
int result = calculateFactorial(n);
cache_[n] = result;
return result;
}
}
private:
// 計算階乘的實際函數(shù)
int calculateFactorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
// 使用一個 unordered_map 來作為緩存
unordered_map<int, int> cache_;
};
int main() {
FactorialCacheProxy cacheProxy;
for (int i = 5; i <= 7; i++) {
int result = cacheProxy.getFactorial(i);
cout << "Factorial of " << i << " is " << result << endl;
}
for (int i = 5; i <= 7; i++) {
int result = cacheProxy.getFactorial(i);
cout << "Factorial of " << i << " is " << result << endl;
}
return 0;
}計算結(jié)果,并將結(jié)果緩存起來。之后再次調(diào)用相同的方法時,直接從緩存中取出結(jié)果,不需要再進行計算,從而提高了程序的性能。
六、總結(jié)
代理模式被代理的對象一定有奇特的地方,要么對象加載困難,要么計算困難,需要設(shè)計一個代理作為緩沖區(qū),在必要時代理才喚醒真正的對象。一切符合上面特性的都可以使用代理模式,設(shè)計模式都是自然而然的,都是解決程序運行中的痛點應運而生的。
以上就是C++利用代理模式實現(xiàn)遠程代理,虛擬代理和保護代理的詳細內(nèi)容,更多關(guān)于C++代理模式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++中String類的常用接口函數(shù)總結(jié)
這篇文章主要介紹了C++中Stirng類的常用接口函數(shù),文中有詳細的代碼示例供大家參考,對我們學習C++有一定的幫助,感興趣的同學可以跟著小編一起來學習2023-06-06
C語言執(zhí)行時,程序控制臺輸出窗口 一閃而過問題及解決
這篇文章主要介紹了C語言執(zhí)行時,程序控制臺輸出窗口 一閃而過問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11

