The proxy design pattern belongs to the structural group that controls the creation and access of objects. A proxy is usually a simple small object between the client code and the real (more complex) object that controls access to the real object. When the conditions are right, the proxy will delegate the client’s request to the actual object for processing.
What is a Proxy Design Pattern in C#?
Imagine a one-stop shop in public offices (like in wards). Although there are many people in the ward in charge of different fields of work, the one-stop shop is the only place where people come into contact.
This department receives all requests from people and checks relevant documents. If the documents are complete and appropriate, the one-stop shop will transfer the documents to the person in charge of the right job for settlement. If the paperwork is incomplete or has errors, the one-stop shop will return it and ask for it to be completed before receiving it.
So what good is this model? Please understand that handling each job at the request of the people is not simple. It takes time and effort. If things go straight to the immediate department, they may have to do things that aren’t really their area of expertise, like checking paperwork. Meanwhile, if the paperwork arrives correctly, they can start their work right away and focus on that.
When there are results from the specialized department, the one-stop-shop will return the results to the people on behalf of the people. At the same time, this department can make additional requests from the people related to the main results.
The one-stop shop works on the idea of a proxy design pattern: controlling access to a specific service; activate the service only when the incoming request matches; perform additional services upon completion of the request.
Now back to the programming world. Imagine the process of accessing a database.
You can allow the client to directly call the database access code.
Problem Solved by Proxy Pattern
However, accessing the database is often complicated, time consuming and processing resources. If the client is not eligible for access or the client’s request does not match, letting the client directly execute the data access code causes a waste of resources.
At this point the proxy model becomes very suitable: a lightweight object (proxy) now stands between the client and the data access code. The proxy checks all conditions before calling the data access code on behalf of the client.
Solution with The Proxy Pattern
UML Diagram of The Proxy Design Pattern in C#
Below is a UML diagram of the Proxy design pattern.
In the above design, there are a few points to note:
Subject is the class that actually helps you handle the request. However, client code will not be able to directly work with objects of this class.
ISubject is an interface with the same method descriptions as that of Subject. In the above diagram, both Subject and ISubject have a Request method. The client will contain (has-a) a variable of type ISubject (and this variable will point to a proxy object).
Proxy is a class that implements the ISubject interface. An object of the Proxy will be contained and used by the client instead of the object of the Subject. Subject methods are called through the Proxy object. In other words, the object of the Proxy will call the actual method of the Subject on behalf of the client.
As you can see, the design diagram of Proxy is quite simple. The key point is that the proxy must have the same method description as the real Subject, while also blocking between the client and the Subject. Client does not call Subject directly, but calls through Proxy. The proxy calls the Subject on behalf of the client. Through this process, the Proxy controls access to the Subject.
Implementing the Proxy Design Pattern in C#
Once you understand the general principle of Proxy, now let’s write a simple program that implements this design pattern.
The program below repeats the design shown above. The program simulates simple account registration from the command line interface.
using System; using Framework; namespace P01_Concept { class Subject : ISubject { public void Request(string name) { ViewHelper.WriteLine($"Hello, {name}. I'm the real subject. I'm doing my job for you", ConsoleColor.Cyan); } } interface ISubject { void Request(string name); } class Proxy : ISubject { private readonly Subject _subject; public Proxy() => _subject = new Subject(); public Proxy(Subject subject) => _subject = subject; public void Request(string name) { ViewHelper.WriteLine($"Hello, {name}. I'm the proxy. Your request will be processing now. Thank you!", ConsoleColor.Yellow); _subject.Request(name); ViewHelper.WriteLine($"Greating! I'm the proxy again. Your work is done, {name}. Goodbye!", ConsoleColor.Green); } } class Program { static ISubject _proxy = new Proxy(); static void Main(string[] args) { var app = new Application { Title = "PROXY DESIGN PATTERN", Config = RegisterRoutes }; app.Run(); } private static void RegisterRoutes() { var router = Router.Instance; router.Register( route: "register", action: (p) => { CreateAccount(p["name"]); }, "Request to register a new account in the system.r\nSyntax: register ? name = ..." ); } private static void CreateAccount(string name) { _proxy.Request(name); } } }
The results of running the program are as follows:
The above simple program re-implements the presented UML design. You will notice that the client code (the Program class) contains the object of the Proxy. It also calls the Proxy’s Request method.
However, the Proxy adds its own directive before and after the actual execution of the Subject. In real situations, this is where the code that controls accessing the actual object is written, as well as performing additional operations.
Conclusion
In this lesson we learned the proxy design pattern and its basic implementation in C#. There are several situations where Proxy can be used:
- You need to control object access;
- You only want to create objects when absolutely necessary;
- Object consumes a lot of resources to initialize and operate;
- Perform additional tasks each time the client accesses the object.
If you feel the site useful, before you leave please help the site with a small action so that it can grow and serve you better.
If you find the article useful, please help share it with everyone.
If you have any questions or need to discuss further, please write in the discussion section at the bottom of the page. Thank you for reading!