Back to: Design Patterns in C# With Real-Time Examples
Proxy Design Pattern in C# with Examples
In this article, I will discuss the Proxy Design Pattern in C# with Examples. Please read our previous article, discussing the Flyweight Design Pattern in C# with Examples. The Proxy Design Pattern falls under the category of Structural Design Pattern. As part of this article, we will discuss the following pointers.
- What is the Proxy Design Pattern?
- Understanding the different types of Proxies.
- Proxy Design Pattern Real-time Examples.
- Why do we need the Proxy Design Pattern in C#
- Implementation of Proxy Design Pattern in C#.
- Understanding the class diagram of the Proxy Design Pattern.
- When to use the Proxy Design Pattern in real-time applications?
What is the Proxy Design Pattern?
According to the Gang of four definitions, the Proxy Design Pattern provides a surrogate (act on behalf of another) or placeholder for another object to control access to it.
The Proxy Design Pattern allows us to create a class that represents the functionality of other classes. The proxy could interface with anything, such as a network connection, a large object in memory, a file, or other resources that are expensive or impossible to duplicate.
We can also say that the Proxy is the object the client calls to access the real object behind the scene. Proxy means in place of or on behalf of. That means, In the Proxy Design Pattern, a class represents the functionality of another class.
Let us understand the above definition with one example. Please look at the following diagram to understand the Proxy Design Pattern in C#. As you can see in the following image, when the client wants to consume some methods of the Real Object, he/she needs to go via the Proxy object. That means the client will call the method of the Proxy object, and the proxy will be responsible for calling the method of the Real Object.
Types of Proxies:
There are three types of proxies. They are as follows.
- Virtual Proxy: A virtual proxy is a placeholder for “expensive to create” objects. The real object is only created when a client first requests or accesses the object.
- Remote Proxy: A remote proxy provides local representation for an object that resides in a different address space.
- Protection Proxy: A protection proxy controls access to a sensitive master object. The surrogate object checks that the caller has the access permissions required before forwarding the request.
Real-Time Example to Understand Proxy Design Pattern:
Please look at the following diagram to better understand the Proxy Design Pattern. On the right-hand side, you can see the State Bank of India; on the left, you can see a person called Anurag. Anurag has an account in the State Bank of India. In earlier days, let’s say 1980, Anurag wanted to withdraw money from his account. Then what he has to do? He has to carry his passbook and go to the bank. Then, he must fill out the form and stand in the queue. Once his turn comes, he has to give the form and bank passbook to the bank employee, and then the bank employee verifies the form and his passbook. And if everything is fine, the bank employee gives the required money to Anurag.
Let’s assume Anurag wants to withdraw money nowadays. So, instead of going to the bank, he can walk to the nearest ATM with his Debit Card. Then, he inserts his Debit Card and enters the pin and withdrawal amount. The ATM will then communicate with the bank, validate the PIN and Amount, and if everything is fine, the ATM will give the money to Anurag immediately. So, instead of going to the bank, Anurag can withdraw Money from the ATM. So, here, the Bank is the Real Object, and the ATM is the Proxy. And I think this is the best Real-Time Example of the Proxy Design Pattern.
Why do we need the Proxy Design Pattern in C#?
Let us understand the need for the Proxy Design Pattern with the example of a Proxy Server. A server that sits between a client application, such as a Web Browser, and a Real Server is called a Proxy Server. The Proxy Server intercepts all the incoming requests for the Real Server to see if it can fulfill them. If not, then it will forward the requests to the Real Server. The Proxy server has two main objectives. They are as follows:
1. Improve Performance using Proxy Server:
The Proxy Servers can drastically improve the performance of the application. This is because it saves the results of a request for a certain period of time. For example, two users, X and Y, want to access a particular resource through the Proxy Server. First, user X requests a particular resource (a list of employees), and the Proxy Server gets the data from the real server. Before sending the data to the client, it caches that resource (list of employees) for some time. Later, user Y also requests the same resource. The Proxy Server, instead of forwarding that request to the Real Server (which is a time-consuming operation), can return the data from the Cache, ultimately improving the application’s performance.
2. Filter Requests using Proxy Server:
The Proxy Servers can also be used to filter incoming requests. For example, a company might use a Proxy Server to prevent its employees from accessing a specific set of websites such as Facebook, Twitter, etc.
Implementation of Proxy Design Pattern in C# (Protection Proxy):
Please have a look at the following diagram. As you can see in the following diagram, we have a shared computer with a shared folder on the right-hand side. On the left-hand side, we have employees who are working on a software farm. The shared computer contains a shared folder that contains confidential information, and only the employee having the role of Manager and CEO can access this shared folder and perform the Read-Write operations. On the other hand, if the employee is a developer, it should not allow access to the shared folder. That is, we need to do some protection. In scenarios like this, the Protection Proxy can be handy.
What we can do here is, in between the employees and the shared computer, we need to introduce the Folder Proxy. What this Folder proxy can do is it will check if the employee’s role is Manager or CEO, and then it allows the employee to access the shared folder and perform the read-write operation. On the other hand, if the employee role is Developer, it will say you don’t have permission to access this folder. We use that kind of protection logic we can write using the Proxy Design Pattern. Within the Folder Proxy, we must write the logic to filter the incoming requests.
Now, I hope you understand the Proxy Design Pattern. Let us proceed and implement the above example using the Proxy Design Pattern in C# step by step.
Note: The Protection Proxy Pattern is a design pattern where the proxy controls access to an underlying object based on certain access rights. It provides a layer of security before allowing operations to be performed on the real object.
Step 1: Creating the Employee class
Create a class file named Employee.cs and copy and paste the following code. As you can see, this is a very simple class having three properties, i.e., Username, Password, and Role, and we also have one Parameterized constructor to initialize these data members.
namespace ProxyDesignPattern { public class Employee { public string Username { get; set; } public string Password { get; set; } public string Role { get; set; } public Employee(string username, string password, string role) { Username = username; Password = password; Role = role; } } }
Step 2: Creating Subject Interface
Create an interface with the name ISharedFolder.cs, and then copy and paste the following code. This interface defines the common methods the Real Object and the Proxy class will implement. Here, we have declared one method called PerformRWOperations, which both Real Object and Proxy Object will implement.
namespace ProxyDesignPattern { // The Subject interface declares common operations for both RealSubject and the Proxy. // As long as the client works with RealSubject using this interface, // you will be able to pass it a proxy instead of a real subject. public interface ISharedFolder { void PerformRWOperations(); } }
Step3: Creating Real Subject
Create a class file named SharedFolder.cs and copy and paste the following code. This class implements the subject (ISharedFolder) interface and provides implementations for the PerformRWOperations. This is the Real Object where the Manager or CEO will perform the Read and Write Operations.
using System; namespace ProxyDesignPattern { // The RealSubject contains some core business logic. // Usually, RealSubjects are capable of doing some useful work which may be very slow or sensitive // A Proxy can solve these issues without any changes to the RealSubject's code. public class SharedFolder : ISharedFolder { public void PerformRWOperations() { Console.WriteLine("Performing Read Write operation on the Shared Folder"); } } }
Step4: Creating the Proxy Object
Create a class file named SharedFolderProxy.cs and copy and paste the following code. This class also implemented the Subject (ISharedFolder) interface and provided implementations for the PerformRWOperations. This Proxy class also holds a reference to the real object, i.e., the private ISharedFolder folder. To the constructor of this class, we are passing the Employee object, and within the PerformRWOperations method, we are checking whether the employee Role is either CEO or MANAGER. If the employee Role is either CEO or MANAGER, then we are Initializing the real object and calling the PerformRWOperations method on the real object else; we are displaying the message that you don’t have permission to access this shared folder.
using System; namespace ProxyDesignPattern { // The Proxy has an interface identical to the RealSubject. class SharedFolderProxy : ISharedFolder { private ISharedFolder folder; private Employee employee; public SharedFolderProxy(Employee emp) { employee = emp; } public void PerformRWOperations() { if (employee.Role.ToUpper() == "CEO" || employee.Role.ToUpper() == "MANAGER") { folder = new SharedFolder(); Console.WriteLine("Shared Folder Proxy makes call to the RealFolder 'PerformRWOperations method'"); folder.PerformRWOperations(); } else { Console.WriteLine("Shared Folder proxy says 'You don't have permission to access this folder'"); } } } }
Step5: Client code
The Client will use the Proxy Object, and the Proxy object will call the Actual Object behind the scenes. In our example, the Main Method of the Program class is going to be the Client, So Please modify the Main method of the Program class as shown below.
using System; namespace ProxyDesignPattern { class Program { static void Main(string[] args) { Console.WriteLine("Client passing employee with Role Developer to folderproxy"); Employee emp1 = new Employee("Anurag", "Anurag123", "Developer"); SharedFolderProxy folderProxy1 = new SharedFolderProxy(emp1); folderProxy1.PerformRWOperations(); Console.WriteLine(); Console.WriteLine("Client passing employee with Role Manager to folderproxy"); Employee emp2 = new Employee("Pranaya", "Pranaya123", "Manager"); SharedFolderProxy folderProxy2 = new SharedFolderProxy(emp2); folderProxy2.PerformRWOperations(); Console.Read(); } } }
Output:
Understanding the Class or UML Diagram Proxy Design Pattern:
To understand the Class or UML Diagram of the Proxy Design Pattern in C#, please look at the following image.
As shown in the above diagram, four participants are involved in the Proxy Design Pattern. They are as follows:
- Subject (ISharedFolder): This is an interface that defines the members that will be implemented by the RealSubject and Proxy class so that the Proxy can be used by the client instead of the RealSubject. In our example, it is the ISharedFolder interface.
- RealSubject (SharedFolder): This is a class that we want to use more efficiently by using the proxy class. This class should implement the Subject Interface. In our example, it is the SharedFolder class.
- Proxy (SharedFolderProxy): This class holds a reference to the RealSubject class and can access RealSubjecr class members as required. It must implement the same interface as the RealSubject to use the two interchangeably. In our example, it is the SharedFolderProxy class.
- Client: This Client will be a class, and the client class will use the Proxy class.
When to use the Proxy Design Pattern in C#?
The Proxy Design Pattern provides a surrogate or placeholder for another object to control access to it. In C# and other object-oriented languages, there are several scenarios where the Proxy pattern is useful. Here’s when you might consider using it:
Remote Proxy:
When: You are working with objects in a different address space or want to represent remote objects as if they were local.
Purpose: Handles the communication details with the remote object, abstracting the intricacies of remote communication from the client.
Virtual Proxy:
When: There’s a need to delay the creation and initialization of resource-intensive objects until they’re needed.
Purpose: Acts as a placeholder for the expensive object and initializes it on demand, optimizing performance (lazy initialization).
Protection Proxy:
When: You want to control access to the object based on access rights or add an additional layer of security.
Purpose: Check if the caller has the necessary permissions before granting access to the object.
Cache Proxy:
When: Repeated requests are made for the same object, and you want to improve performance by caching the result.
Purpose: Maintains temporary storage of results from expensive or frequently-used operations, preventing repeated calculations or fetches.
Logging Proxy:
When: You want to record the operations performed on an object for auditing or debugging purposes.
Purpose: Adds logging behavior every time an operation is requested on the object.
Monitoring or Synchronization Proxy:
When: You’re working in a multi-threaded environment and want to ensure that the object is accessed only one thread at a time.
Purpose: Ensures synchronized access to the actual object, preventing race conditions.
Smart Reference Proxy:
When: You need to perform additional actions or housekeeping tasks when accessing an object. This might include counting references to an object, loading or evicting objects from memory, etc.
Purpose: Performs extra actions before or after invoking the operations on the real object.
Firewall Proxy:
When: You want to protect networked resources from malicious attacks or control data access going in or out.
Purpose: Acts as an intermediary layer to filter incoming or outgoing requests based on pre-defined rules.
When to use the Proxy Design Pattern in C# Real-Time Applications?
Instead of allowing all users to access specific resources or functions of an object, we want to ensure that only certain users can access those resources or functions at any given time. We can easily achieve this functionality using the Proxy Design Pattern in C#. The following are some real-time scenarios for using the Proxy Design Pattern.
- Adding security access to an existing object. The proxy will determine if the client can access the object or not.
- Simplifying the API of a complex object. The proxy can provide a simple API so that the client code does not have to deal with the complexity of the object of interest.
- Providing interfaces for remote resources such as web service or REST resources.
- Coordinating expensive operations on remote resources by asking the remote resources to start the operation as soon as possible before accessing the resources.
- Adding a thread-safe feature to an existing class without changing the existing class code.
In the next article, I will discuss the Real-Time Example of the Virtual Proxy Design Pattern in C#. Here, in this article, I try to explain the Protection Proxy Design Pattern in C# with Examples. I hope you enjoy this Protection Proxy Design Pattern in C# with Examples article.