Proxy Design Pattern in Java

Proxy Design Pattern in Java with Examples

In this article, I am going to discuss Proxy Design Pattern in Java with Examples. Please read our previous article where we discussed Flyweight Design Pattern in Java with Examples. The Proxy Design Pattern falls under the category of the Structural Design Pattern. In this article, we will explore the fundamental principles and benefits of the Proxy Design Pattern in Java, highlighting its significance in diverse software development scenarios.

What is Proxy Design Pattern?

In software development, managing access to resources and controlling interactions between components is a common challenge. The Proxy design pattern emerges as a valuable solution to address these concerns. By providing a surrogate or placeholder for another object, the Proxy pattern enables flexible control over access and enhances functionality without modifying the underlying object.

The Proxy design pattern is a structural pattern that involves creating a surrogate object that acts as a substitute for another object. This surrogate, known as the proxy, controls access to the real object and adds additional functionality if required. The proxy and the real object share the same interface, enabling transparent substitution. The Proxy pattern can be applied in various situations, such as managing expensive resources, enforcing access control, providing a remote interface, or implementing lazy loading.

According to the Gang of four definitions, 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 some other resources that are expensive or impossible to duplicate.

Let us understand the above definition with one example. Please have a look at the following diagram for a better understanding of the Proxy Design Pattern in Java. As you can see in the following image, when the client wants to consume some methods of the Real Object, then 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 to call the method of the Real Object.

What is Proxy Design Pattern?

Real-Time Example to Understand Proxy Design Pattern:

Please have a look at the following diagram for a better understanding of the Proxy Design Pattern. On the right-hand side, you can see the State Bank of India, and on the left-hand side, you can see a person called Anurag. Anurag has an account in the State Bank of India. In earlier days, let’s say 1990, Anurag wants 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 has to fill out the form and needs to 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 then the bank employee gives the required money to Anurag.

Real-Time Example to Understand Proxy Design Pattern

Let’s assume Anurag wants to withdraw money nowadays. So, instead of going to the bank what he can do nowadays is, just walks to the nearest ATM with his Debit Card. Then he inserts his Debit Card and enters the pin and the amount to withdraw. The ATM will then communicate with the bank, validate the Pin and Amount and if everything is fine then 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 ATM is the Proxy. And I think this is the best Real-Time Example of the Proxy Design Pattern.

Proxy Design Pattern in Java with Examples

Understanding the Class or UML Diagram Proxy Design Pattern:

In order to understand the Class or UML Diagram of the Proxy Design Pattern in Java, please have a look at the following image.

Understanding the Class or UML Diagram Proxy Design Pattern

As shown in the above diagram, there are four participants involved in the Proxy Design Pattern. They are as follows:

  1. Subject: This is an interface that defines the members that are going to be implemented by the RealSubject and Proxy class so that the Proxy can be used by the client instead of the RealSubject.
  2. RealSubject: This is a class that we want to use more efficiently by using the proxy class. This class should implement the Subject Interface.
  3. Proxy: This is a class that holds a reference to the RealSubject class and can access RealSubjecr class members as required. It must implement the same interface as the RealSubject so that the two can be used interchangeably.
  4. Client: This Client is going to be a class and the client class is going to use the Proxy class.
Example to Understand Proxy Design Pattern in Java

A real-world example where the Proxy pattern can be applied is the internet. In this scenario, clients need to access the internet. The Proxy pattern can be used to provide a proxy object that handles the communication and access to the internet.

The proxy object acts as a surrogate for the internet. It intercepts the requests from the clients and performs additional operations such as authentication, authorization, or caching before providing access to the internet.

By using the Proxy pattern, access to the internet can be controlled and additional operations can be performed transparently. The proxy ensures that clients have the necessary permissions to access the internet and provides an extra layer of security. The UML Diagram of this example is given below using Proxy Design Pattern.

Example to Understand Proxy Design Pattern in Java

Implementing Proxy Design Pattern in Java

Step 1: Create a new directory to store all the class files of this project.

Step 2: Open VS Code and create a new project, called proxy.

Step 3: In the project, create a new file called InternetAccess.java. Add the following code to the file:

Implementing Proxy Design Pattern in Java

This is the interface from which other concrete classes will be created.

Step 4: In the project, create a new file called RealInternetAccess.java. Add the following code to the file:

Proxy Design Pattern in Java

Step 5: In the project, create a new file called ProxyInternetAccess.java. Add the following code to the file:

Proxy Design Pattern in Java with Examples

This class will be called whenever a new internet connection needs to be created. Based on whether the customer has paid their bill, the customer will be granted real internet access. In this case, we have used a random function to check if the user has paid their bill. When implementing a similar program in a real-life scenario, the programmer must always check properly (by searching the payments database or so).

Step 6: In the project, create a new file called ProxyPatternDemo.java. This class will contain the main() function. Write the main() function in ProxyPatternDemo.java:

Proxy Pattern in Java

This main function creates new customers and checks for its internet connection. If the customer has paid their bill, they will be granted internet access.

Step 7: Compile and execute the application. Ensure compilation is successful. Verify that the program works as expected. Because we are using a random variable in the ProxyInternetAccess.java class, we shall not get the same answer each time. Run the code multiple times.

Congratulations! You now know how to implement proxy patterns!

UML Diagram of Proxy Design Pattern:

Now, let us see the Proxy Design Pattern UML Diagram Components with our Example so that you can easily understand the UML Diagram.

UML Diagram of Proxy Design Pattern

The classes can be described as follows:

  1. Object: This class contains the definitions for the functions. These functions will later be implemented in the concrete classes.
  2. ConcreteObject: This class implements the functions defined in the aforementioned interface.
  3. DriverClass: This class contains the main() function and is responsible for handling the simulation of the program.
The Complete Example Code of Proxy Design Pattern in Java
InternetAccess.java
public interface InternetAccess
{
    public void grantInternetAccess();
}
ProxyInternetAccess.java
import java.util.Random;

public class ProxyInternetAccess implements InternetAccess
{
    private String name;
    private RealInternetAccess ria;

    public ProxyInternetAccess(String name) {
        this.name = name;
    }

    @Override
    public void grantInternetAccess()
    {
        if (billPaid())
        {
            ria = new RealInternetAccess(name);
            ria.grantInternetAccess();
        }
        else
        {
            System.out.println("Internet access not granted!");
            System.out.println("You have not paid your bill!");
        }
    }

    private boolean billPaid ()
    {
        return (new Random().nextInt(2) == 1);
    }
}
ProxyPatternDemo.java
public class ProxyPatternDemo
{
    public static void main(String[] args) {
        InternetAccess i = new ProxyInternetAccess("Customer A");
        i.grantInternetAccess();
    }    
}
RealInternetAccess.java
public class RealInternetAccess implements InternetAccess
{
    private String name;

    public RealInternetAccess(String name) {
        this.name = name;
    }

    @Override
    public void grantInternetAccess()
    {
        System.out.println("Internet access granted for " + name);
    }
}
Advantages of Proxy Design Pattern in Java:

Some of the Advantages of the Proxy Design Pattern in Java are as follows:

  • Access Control: The Proxy pattern allows fine-grained control over object access. The proxy acts as a gatekeeper, verifying permissions or conditions before allowing access to the real object. This control helps enforce security policies, restrict unauthorized operations, or implement access restrictions based on user roles or privileges.
  • Resource Management: Proxies can manage expensive resources, such as database connections, network connections, or memory-intensive objects. By using a proxy, resources can be allocated and released based on demand, optimizing their utilization. This approach helps improve performance, scalability, and overall system efficiency.
  • Remote Communication: The Proxy pattern enables the implementation of distributed systems by providing a remote interface. Proxies can act as representatives for objects residing in different locations or on remote servers. Clients can interact with the proxy as if it were the real object, while the proxy handles the underlying communication protocols and network complexities.
  • Lazy Loading: Proxies can defer the creation or loading of resource-intensive objects until they are actually needed. This lazy loading technique improves startup times, reduces memory usage, and enhances application responsiveness. Proxies can dynamically load and instantiate objects, allowing clients to work with placeholders until the actual object is required.
  • Additional Functionality: Proxies can extend the behavior of the real object by providing additional functionalities. For example, a logging proxy can record method invocations, a caching proxy can store results for future requests, or a validation proxy can perform input validation before forwarding requests to the real object. This capability allows developers to enhance or modify object behavior without directly modifying the original object.
Disadvantages of Proxy Design Pattern in Java:

Some of the Disadvantages of the Proxy Design Pattern in Java are as follows:

  • Increased complexity: Introducing a proxy object can add an extra layer of complexity to the system. This can make the overall design more intricate and harder to understand and maintain, especially when dealing with multiple proxy types or complex interactions between the proxy and the real object.
  • Performance overhead: Depending on the implementation, the use of a proxy can introduce additional overhead, leading to a potential decrease in performance. For example, if the proxy performs expensive operations like network communication or caching, it may impact the response time and efficiency of the system.
  • Reduced transparency: While the proxy aims to provide a transparent interface to the clients, it may not always fully replicate the behavior of the real object. Certain operations or functionalities may be limited or unavailable in the proxy, which can cause confusion or unexpected behavior for clients relying on the proxy.
  • Synchronization issues: If multiple clients access the same proxy concurrently, synchronization issues may arise. Proper synchronization mechanisms need to be implemented in the proxy to ensure thread safety and prevent race conditions or data inconsistencies.
  • Increased development effort: Implementing the proxy pattern requires additional development effort. The creation of proxy classes and ensuring proper coordination between the proxy and the real object may add complexity and increase the time and effort required for the development.

In the next article, I am going to discuss Facade Design Pattern in Java with Examples. Here, in this article, I try to explain Proxy Design Pattern in Java with Examples. I hope you understood the need for and use of Proxy Design Pattern in Java.

Leave a Reply

Your email address will not be published. Required fields are marked *