Skip to main content

Proxy Design Pattern

Problem​

You: Hi Shubh, recently I got a task from my manager. I've built a system where we can create employees in the database and also fetch the list of employees.

Shubh: Oh nice! You're making progress in your career. I hope your manager is happy with you! 😄

You: Haha, the task is not over yet. I need to restrict access to certain functionality.

Shubh: Which one?

You: The creation of a new employee. Only an admin should be able to create a new employee. I'm thinking of adding this logic in the createEmployee() function itself.

Shubh: You could do that, but that wouldn't be a good idea! Your server should always focus on business logic. Let a proxy handle access-related stuff. You should use the Proxy Design Pattern.

You: Proxy Design Pattern? I haven't heard about it.

Shubh: The Proxy Pattern is used for various purposes like access control, caching, etc. We can create a dedicated proxy class to handle such scenarios.

UML​

Proxy Design Pattern

UML for Proxy Design Pattern

Shubh: In this UML diagram:

  1. ISubject Interface: This is implemented by the RealSubject. In our example, EmployeeDAO is an interface implemented by EmployeeDAOImpl.

  2. Proxy isA ISubject: This relationship is known as inheritance. It means the Proxy class knows all the functionalities that need to be implemented.

  3. Proxy hasA RealSubject: This relationship is known as association. It means the Proxy class can add certain logic, like access control, before calling the functionality of the RealSubject. The client interacts with the proxy, which then adds additional logic before calling the real subject's functionality.

Code Implementation​

Employee Class​

Employee.java
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Employee {
private String name;
private String id;
private Role role;

public Employee(String name, String id, Role role) {
this.name = name;
this.id = id;
this.role = role;
}
}

EmployeeDAO Interface​

EmployeeDAO.java
public interface EmployeeDAO {
void createEmployee(Employee employee);
Employee getEmployee(String id);
}

EmployeeDAOImpl Class​

EmployeeDAOImpl.java
public class EmployeeDAOImpl implements EmployeeDAO {
@Override
public void createEmployee(Employee employee) {
System.out.println("Employee with name " + employee.getName() + " created");
}

@Override
public Employee getEmployee(String id) {
System.out.println("Fetching employee with id: " + id);
return new Employee("Shubh", "1", Role.ADMIN);
}
}

EmployeeDAOProxy Class​

EmployeeDAOProxy.java
public class EmployeeDAOProxy implements EmployeeDAO {
private EmployeeDAO employeeDAO;

EmployeeDAOProxy(EmployeeDAO employeeDAO) {
this.employeeDAO = employeeDAO;
}

@Override
public void createEmployee(Employee employee) {
if (employee.getRole() == Role.ADMIN) {
employeeDAO.createEmployee(employee);
} else {
System.out.println("ACCESS DENIED");
}
}

@Override
public Employee getEmployee(String id) {
return employeeDAO.getEmployee(id);
}
}

Role Enum​

Role.java
public enum Role {
ADMIN, USER
}

Main Class (Client Code)​

Main.java
public class Main {
public static void main(String[] args) {
EmployeeDAO employeeDAOProxy = new EmployeeDAOProxy(new EmployeeDAOImpl());

Employee employee1 = new Employee("Shubh", "1", Role.ADMIN);
Employee employee2 = new Employee("Kunal", "2", Role.USER);

System.out.println("------------------------------");
employeeDAOProxy.createEmployee(employee1);
employeeDAOProxy.getEmployee("1");

System.out.println("------------------------------");
employeeDAOProxy.createEmployee(employee2);
employeeDAOProxy.getEmployee("2");
}
}

Key Benefits of the Proxy Design Pattern​

Before watching, make sure you give it a try
  1. Access Control: The Proxy can control access to the actual object. In our example, it restricts the creation of employees to admins only.

  2. Logging and Auditing: Proxies can be used to add logging or auditing functionality before or after invoking methods on the RealSubject.