Open In App

Proxy Method Design Pattern in Java

A Proxy Method or Proxy Design Pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. This pattern involves creating a new class, known as the proxy, which acts as an intermediary between a client and the real object. The proxy object controls access to the real object, allowing you to add additional functionality, such as lazy loading, access control, logging, or caching, without changing the actual object’s code.



Example of Proxy Method Design Pattern in Java

Problem Statement:

We have to create a simple banking application with a proxy to control access to the real bank account.



Key Concepts of Proxy Method Design Pattern in Java

Step wise Step Implementation of above Proxy Method Design Pattern in Java:

“BankAccount” (Subject Interface): This is the subject interface that both the real and proxy objects will implement. It declares three methods: “deposit”, “withdraw,” and “getBalance”.




// Subject interface
interface BankAccount {
    void deposit(double amount);
    void withdraw(double amount);
    double getBalance();
}

“RealBankAccount” (RealSubject) Class: “RealBankAccount” is the real subject class implementing the “BankAccount” interface. It maintains a balance and provides implementations for the deposit, withdraw, and getBalance methods.




// RealSubject class
class RealBankAccount implements BankAccount {
    private double balance;
 
    @Override
    public void deposit(double amount) {
        balance += amount;
        System.out.println("Deposited: " + amount);
    }
 
    @Override
    public void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println("Withdrawn: " + amount);
        } else {
            System.out.println("Insufficient funds!");
        }
    }
 
    @Override
    public double getBalance() {
        return balance;
    }
}

“SecureBankAccountProxy” (Proxy) Class: “SecureBankAccountProxy” is the proxy class implementing the BankAccount interface. It contains a reference to the real bank account (“RealBankAccount”) and requires a password for authentication during instantiation. The “authenticate” method checks the password and initializes the real bank account if authentication is successful. The “deposit”, “withdraw”, and “getBalance” methods delegate to the corresponding methods of the real bank account.




// Proxy class
class SecureBankAccountProxy implements BankAccount {
    private RealBankAccount realBankAccount;
    private String password;
 
    public SecureBankAccountProxy(String password) {
        this.password = password;
        authenticate();
    }
 
    private void authenticate() {
        if (password.equals("secret")) {
            realBankAccount = new RealBankAccount();
            System.out.println("Authentication successful.");
        } else {
            System.out.println("Authentication failed. Access denied.");
        }
    }
 
    @Override
    public void deposit(double amount) {
        if (realBankAccount != null) {
            realBankAccount.deposit(amount);
        }
    }
 
    @Override
    public void withdraw(double amount) {
        if (realBankAccount != null) {
            realBankAccount.withdraw(amount);
        }
    }
 
    @Override
    public double getBalance() {
        return (realBankAccount != null) ? realBankAccount.getBalance() : 0.0;
    }
}

“ProxyBankExample” Class (Client): “ProxyBankExample” is the client code that demonstrates the usage of the proxy. It creates an instance of “SecureBankAccountProxy” and performs deposit, withdrawal, and balance retrieval operations.




// Client code
public class ProxyBankExample {
    public static void main(String[] args) {
        // Using the proxy to access the real bank account
        BankAccount account = new SecureBankAccountProxy("secret");
 
        // Operations
        account.deposit(1000);
        account.withdraw(500);
        double balance = account.getBalance();
 
        System.out.println("Current Balance: " + balance);
    }
}

Below is the complete combined code of the above example:

To run this code correctly, copy this code and save it in a file named “ProxyBankExample.java”.




// Subject interface
interface BankAccount {
    void deposit(double amount);
    void withdraw(double amount);
    double getBalance();
}
 
// RealSubject class
class RealBankAccount implements BankAccount {
    private double balance;
 
    @Override
    public void deposit(double amount) {
        balance += amount;
        System.out.println("Deposited: " + amount);
    }
 
    @Override
    public void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println("Withdrawn: " + amount);
        } else {
            System.out.println("Insufficient funds!");
        }
    }
 
    @Override
    public double getBalance() {
        return balance;
    }
}
 
// Proxy class
class SecureBankAccountProxy implements BankAccount {
    private RealBankAccount realBankAccount;
    private String password;
 
    public SecureBankAccountProxy(String password) {
        this.password = password;
        authenticate();
    }
 
    private void authenticate() {
        if (password.equals("secret")) {
            realBankAccount = new RealBankAccount();
            System.out.println("Authentication successful.");
        } else {
            System.out.println("Authentication failed. Access denied.");
        }
    }
 
    @Override
    public void deposit(double amount) {
        if (realBankAccount != null) {
            realBankAccount.deposit(amount);
        }
    }
 
    @Override
    public void withdraw(double amount) {
        if (realBankAccount != null) {
            realBankAccount.withdraw(amount);
        }
    }
 
    @Override
    public double getBalance() {
        return (realBankAccount != null) ? realBankAccount.getBalance() : 0.0;
    }
}
 
// Client code
public class ProxyBankExample {
    public static void main(String[] args) {
        // Using the proxy to access the real bank account
        BankAccount account = new SecureBankAccountProxy("secret");
 
        // Operations
        account.deposit(1000);
        account.withdraw(500);
        double balance = account.getBalance();
 
        System.out.println("Current Balance: " + balance);
    }
}

Output
Authentication successful.
Deposited: 1000.0
Withdrawn: 500.0
Current Balance: 500.0


Diagrammatical Representation of the Proxy Method Design Pattern in Java

In this representation:

The arrows represent the relationships between the classes:

Use Cases of Proxy Method Design Pattern in Java

Advantages of the Proxy Method Design Pattern in Java

Disadvantages of the Proxy Method Design Pattern in Java

Conclusion

The Proxy Method Design Pattern in Java is a valuable tool for enhancing control, security, and performance in software systems. When applied correctly and carefully, this pattern provides a modular and flexible approach to extending or modifying the behavior of objects. The pattern provides an effective mechanism for controlling access, optimizing performance, and adding functionalities without directly altering the original object.


Article Tags :