Usage examples: While the Proxy pattern isn’t a frequent guest in most C# applications, it’s still very handy in some special cases. It’s irreplaceable when you want to add some additional behaviors to an object of some existing class without changing the client code.
Identification: Proxies delegate all of the real work to some other object. Each proxy method should, in the end, refer to a service object unless the proxy is a subclass of a service.
Conceptual Example
This example illustrates the structure of the Proxy design pattern. It focuses on answering these questions:
What classes does it consist of?
What roles do these classes play?
In what way the elements of the pattern are related?
Program.cs: Conceptual example
usingSystem;namespaceRefactoringGuru.DesignPatterns.Proxy.Conceptual{ // 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.publicinterfaceISubject {voidRequest(); } // 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.classRealSubject:ISubject {publicvoidRequest() {Console.WriteLine("RealSubject: Handling Request."); } } // The Proxy has an interface identical to the RealSubject.classProxy:ISubject {privateRealSubject _realSubject;publicProxy(RealSubject realSubject) {this._realSubject= realSubject; } // 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.publicvoidRequest() {if (this.CheckAccess()) {this._realSubject.Request();this.LogAccess(); } }publicboolCheckAccess() { // Some real checks should go here.Console.WriteLine("Proxy: Checking access prior to firing a real request.");returntrue; }publicvoidLogAccess() {Console.WriteLine("Proxy: Logging the time of request."); } }publicclassClient { // 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.publicvoidClientCode(ISubject subject) { // ...subject.Request(); // ... } }classProgram {staticvoidMain(string[] args) {Client client =newClient();Console.WriteLine("Client: Executing the client code with a real subject:");RealSubject realSubject =newRealSubject();client.ClientCode(realSubject);Console.WriteLine();Console.WriteLine("Client: Executing the same client code with a proxy:");Proxy proxy =newProxy(realSubject);client.ClientCode(proxy); } }}
Output.txt: Execution result
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.