|
| 1 | +#include <iostream> |
| 2 | +/** |
| 3 | + * EN: Proxy Design Pattern |
| 4 | + * |
| 5 | + * Intent: Provide a surrogate or placeholder for another object to control |
| 6 | + * access to the original object or to add other responsibilities. |
| 7 | + * |
| 8 | + * RU: Паттерн Заместитель |
| 9 | + * |
| 10 | + * Назначение: Позволяет подставлять вместо реальных объектов специальные |
| 11 | + * объекты-заменители. Эти объекты перехватывают вызовы к оригинальному объекту, |
| 12 | + * позволяя сделать что-то до или после передачи вызова оригиналу. |
| 13 | + */ |
| 14 | +/** |
| 15 | + * EN: The Subject interface declares common operations for both RealSubject and |
| 16 | + * the Proxy. As long as the client works with RealSubject using this interface, |
| 17 | + * you'll be able to pass it a proxy instead of a real subject. |
| 18 | + * |
| 19 | + * RU: Интерфейс Субъекта объявляет общие операции как для Реального Субъекта, |
| 20 | + * так и для Заместителя. Пока клиент работает с Реальным Субъектом, используя |
| 21 | + * этот интерфейс, вы сможете передать ему заместителя вместо реального |
| 22 | + * субъекта. |
| 23 | + */ |
| 24 | +class Subject |
| 25 | +{ |
| 26 | +public: |
| 27 | + virtual void Request() const = 0; |
| 28 | +}; |
| 29 | +/** |
| 30 | + * EN: The RealSubject contains some core business logic. Usually, RealSubjects |
| 31 | + * are capable of doing some useful work which may also be very slow or |
| 32 | + * sensitive - e.g. correcting input data. A Proxy can solve these issues |
| 33 | + * without any changes to the RealSubject's code. |
| 34 | + * |
| 35 | + * RU: Реальный Субъект содержит некоторую базовую бизнес-логику. Как правило, |
| 36 | + * Реальные Субъекты способны выполнять некоторую полезную работу, которая к |
| 37 | + * тому же может быть очень медленной или точной – например, коррекция входных |
| 38 | + * данных. Заместитель может решить эти задачи без каких-либо изменений в коде |
| 39 | + * Реального Субъекта. |
| 40 | + */ |
| 41 | +class RealSubject : public Subject |
| 42 | +{ |
| 43 | +public: |
| 44 | + void Request() const override |
| 45 | + { |
| 46 | + std::cout << "RealSubject: Handling request.\n"; |
| 47 | + } |
| 48 | +}; |
| 49 | +/** |
| 50 | + * EN: The Proxy has an interface identical to the RealSubject. |
| 51 | + * |
| 52 | + * RU: Интерфейс Заместителя идентичен интерфейсу Реального Субъекта. |
| 53 | + */ |
| 54 | +class Proxy : public Subject |
| 55 | +{ |
| 56 | + /** |
| 57 | + * @var RealSubject |
| 58 | + */ |
| 59 | +private: |
| 60 | + RealSubject *real_subject_; |
| 61 | + |
| 62 | + bool CheckAccess() const |
| 63 | + { |
| 64 | + // EN: Some real checks should go here. |
| 65 | + // |
| 66 | + // RU: Некоторые реальные проверки должны проходить здесь. |
| 67 | + std::cout << "Proxy: Checking access prior to firing a real request.\n"; |
| 68 | + return true; |
| 69 | + } |
| 70 | + void LogAccess() const |
| 71 | + { |
| 72 | + std::cout << "Proxy: Logging the time of request.\n"; |
| 73 | + } |
| 74 | + |
| 75 | + /** |
| 76 | + * EN: The Proxy maintains a reference to an object of the RealSubject |
| 77 | + * class. It can be either lazy-loaded or passed to the Proxy by the client. |
| 78 | + * |
| 79 | + * RU: Заместитель хранит ссылку на объект класса РеальныйСубъект. Клиент |
| 80 | + * может либо лениво загрузить его, либо передать Заместителю. |
| 81 | + */ |
| 82 | +public: |
| 83 | + Proxy(RealSubject *real_subject) : real_subject_(new RealSubject(*real_subject)) |
| 84 | + { |
| 85 | + } |
| 86 | + |
| 87 | + ~Proxy() |
| 88 | + { |
| 89 | + delete real_subject_; |
| 90 | + } |
| 91 | + /** |
| 92 | + * EN: The most common applications of the Proxy pattern are lazy loading, |
| 93 | + * caching, controlling the access, logging, etc. A Proxy can perform one of |
| 94 | + * these things and then, depending on the result, pass the execution to the |
| 95 | + * same method in a linked RealSubject object. |
| 96 | + * |
| 97 | + * RU: Наиболее распространёнными областями применения паттерна Заместитель |
| 98 | + * являются ленивая загрузка, кэширование, контроль доступа, ведение журнала |
| 99 | + * и т.д. Заместитель может выполнить одну из этих задач, а затем, в |
| 100 | + * зависимости от результата, передать выполнение одноимённому методу в |
| 101 | + * связанном объекте класса Реального Субъект. |
| 102 | + */ |
| 103 | + void Request() const override |
| 104 | + { |
| 105 | + if (this->CheckAccess()) |
| 106 | + { |
| 107 | + this->real_subject_->Request(); |
| 108 | + this->LogAccess(); |
| 109 | + } |
| 110 | + } |
| 111 | +}; |
| 112 | +/** |
| 113 | + * EN: The client code is supposed to work with all objects (both subjects and |
| 114 | + * proxies) via the Subject interface in order to support both real subjects and |
| 115 | + * proxies. In real life, however, clients mostly work with their real subjects |
| 116 | + * directly. In this case, to implement the pattern more easily, you can extend |
| 117 | + * your proxy from the real subject's class. |
| 118 | + * |
| 119 | + * RU: Клиентский код должен работать со всеми объектами (как с реальными, так и |
| 120 | + * заместителями) через интерфейс Субъекта, чтобы поддерживать как реальные |
| 121 | + * субъекты, так и заместителей. В реальной жизни, однако, клиенты в основном |
| 122 | + * работают с реальными субъектами напрямую. В этом случае, для более простой |
| 123 | + * реализации паттерна, можно расширить заместителя из класса реального |
| 124 | + * субъекта. |
| 125 | + */ |
| 126 | +void ClientCode(const Subject &subject) |
| 127 | +{ |
| 128 | + // ... |
| 129 | + subject.Request(); |
| 130 | + // ... |
| 131 | +} |
| 132 | + |
| 133 | +int main() |
| 134 | +{ |
| 135 | + std::cout << "Client: Executing the client code with a real subject:\n"; |
| 136 | + RealSubject *real_subject = new RealSubject; |
| 137 | + ClientCode(*real_subject); |
| 138 | + std::cout << "\n"; |
| 139 | + std::cout << "Client: Executing the same client code with a proxy:\n"; |
| 140 | + Proxy *proxy = new Proxy(real_subject); |
| 141 | + ClientCode(*proxy); |
| 142 | + |
| 143 | + delete real_subject; |
| 144 | + delete proxy; |
| 145 | + return 0; |
| 146 | +} |
0 commit comments