![Замісник](/images/patterns/cards/proxy-mini.png?id=25890b11e7dc5af29625ccd0678b63a8)
Замісник на C++
Замісник — це об’єкт, який виступає прошарком між клієнтом та реальним сервісним об’єктом. Замісник отримує виклики від клієнта, виконує свою функцію (контроль доступу, кешування, зміна запиту та інше), а потім передає виклик сервісному об’єктові.
Замісник має той самий інтерфейс, що і реальний об’єкт, тому для клієнта немає різниці — працювати з реальним об’єктом безпосередньо, чи за допомогою замісника.
Складність:
Популярність:
Застосування: Патерн Замісник застосовується в коді на C++ тоді, коли потрібно замінити дійсний об’єкт його сурогатом, причому, непомітно для клієнтів цього об’єкта. Це дозволить виконати додаткові поведінки до або після основної поведінки дійсного об’єкта.
Ознаки застосування патерна: Клас замісника найчастіше делегує всю справжню роботу своєму реальному об’єктові. Замісники часто самі стежать за життєвим циклом свого реального об’єкта.
Концептуальний приклад
Цей приклад показує структуру патерна Замісник, а саме — з яких класів він складається, які ролі ці класи виконують і як вони взаємодіють один з одним.
main.cc: Приклад структури патерна
#include <iostream>
/**
* The Subject interface declares common operations for both RealSubject and the
* Proxy. As long as the client works with RealSubject using this interface,
* you'll be able to pass it a proxy instead of a real subject.
*/
class Subject {
public:
virtual void Request() const = 0;
};
/**
* The RealSubject contains some core business logic. Usually, RealSubjects are
* capable of doing some useful work which may also be very slow or sensitive -
* e.g. correcting input data. A Proxy can solve these issues without any
* changes to the RealSubject's code.
*/
class RealSubject : public Subject {
public:
void Request() const override {
std::cout << "RealSubject: Handling request.\n";
}
};
/**
* The Proxy has an interface identical to the RealSubject.
*/
class Proxy : public Subject {
/**
* @var RealSubject
*/
private:
RealSubject *real_subject_;
bool CheckAccess() const {
// Some real checks should go here.
std::cout << "Proxy: Checking access prior to firing a real request.\n";
return true;
}
void LogAccess() const {
std::cout << "Proxy: Logging the time of request.\n";
}
/**
* The Proxy maintains a reference to an object of the RealSubject class. It
* can be either lazy-loaded or passed to the Proxy by the client.
*/
public:
Proxy(RealSubject *real_subject) : real_subject_(new RealSubject(*real_subject)) {
}
~Proxy() {
delete real_subject_;
}
/**
* The most common applications of the Proxy pattern are lazy loading,
* caching, controlling the access, logging, etc. A Proxy can perform one of
* these things and then, depending on the result, pass the execution to the
* same method in a linked RealSubject object.
*/
void Request() const override {
if (this->CheckAccess()) {
this->real_subject_->Request();
this->LogAccess();
}
}
};
/**
* The client code is supposed to work with all objects (both subjects and
* proxies) via the Subject interface in order to support both real subjects and
* proxies. In real life, however, clients mostly work with their real subjects
* directly. In this case, to implement the pattern more easily, you can extend
* your proxy from the real subject's class.
*/
void ClientCode(const Subject &subject) {
// ...
subject.Request();
// ...
}
int main() {
std::cout << "Client: Executing the client code with a real subject:\n";
RealSubject *real_subject = new RealSubject;
ClientCode(*real_subject);
std::cout << "\n";
std::cout << "Client: Executing the same client code with a proxy:\n";
Proxy *proxy = new Proxy(real_subject);
ClientCode(*proxy);
delete real_subject;
delete proxy;
return 0;
}
Output.txt: Результат виконання
Client: Executing the client code with a real subject:
RealSubject: Handling request.
Client: Executing the same client code with a proxy:
Proxy: Checking access prior to firing a real request.
RealSubject: Handling request.
Proxy: Logging the time of request.