Today, let's take a look at what the proxy design pattern is. As the name suggests, a proxy is a middleman who replaces someone to do something. In our program, a proxy object is used to control the access to a specific method of a concrete object. Some additional processing can be done before and after the method.
- Understanding the concept
- Static proxy
- Dynamic proxy
Understanding the concept#
- Abstract role: Used to define the common methods between the real role and the proxy role.
- Real role: The concrete business logic that the real role needs to implement for the proxy role to call.
- Proxy role: Used to proxy the real role. Additional processing can be done before and after the specific logic of the real role.
So, the significance of a proxy is that the specific business logic is only called when needed. Any processing unrelated to the specific business logic of the real role is handled in the proxy class.
Static proxy#
Let's first take a look at the code implementation of static proxy. Define the abstract role to declare the shared business logic, as follows:
/**
* Abstract role
*/
public interface IBusiness {
/**
* Shopping
*/
void buy();
}
Then, create the real role and complete the specific business logic, as follows:
/**
* Real role
*/
public class RealRole implements IBusiness{
@Override
public void buy() {
System.out.println("I want to buy something");
}
}
Next, create the proxy role. When performing the specific business logic, the business logic method of the real role must be called, as follows:
/**
* Proxy role
*/
public class ProxyRole implements IBusiness{
private IBusiness mRealRole;
public ProxyRole(IBusiness realRole) {
this.mRealRole = realRole;
}
@Override
public void buy() {
// Additional evaluation before purchase
System.out.println("Additional evaluation before purchase...");
// Specific business logic
mRealRole.buy();
// Satisfaction survey after purchase
System.out.println("Satisfaction survey after purchase...");
}
}
Finally, use the static proxy class created earlier, as follows:
/**
* Test static proxy
*/
public class StaticClient {
public static void main(String[] args) {
// Create the real role
IBusiness realRole = new RealRole();
// Create the proxy role
IBusiness proxyRole = new ProxyRole(realRole);
// The proxy role helps you buy things
proxyRole.buy();
}
}
The test result is as follows:
Additional evaluation before purchase...
I want to buy something
Satisfaction survey after purchase...
In this example, the proxy not only helps us buy things, but also does some additional processing before and after the purchase behavior. It is quite flexible, isn't it?
Dynamic proxy#
Now that we have learned about static proxy, what is the difference between dynamic proxy and static proxy? In fact, the main difference between static proxy and dynamic proxy is that static proxy requires manually generating proxy classes, while dynamic proxy automatically generates proxy classes during the code execution process. Let's take a look at the key classes or interfaces provided by the Java JDK for implementing dynamic proxy. They are as follows:
// Used to dynamically generate proxy classes and their objects
java.lang.reflect.Proxy
// The interface that the invocation handler of the proxy role needs to implement
// When the abstract role calls the method, it will be called by the invoke method of this interface
java.lang.reflect.InvocationHandler
Next, let's implement the dynamic proxy provided by the Java JDK. First, the abstract role and the real role are the same as the static proxy, so I won't repeat them here. Create a invocation handler for the proxy role as follows:
/**
* Invocation handler for the proxy role
*/
public class BusinessHandler implements InvocationHandler{
private IBusiness mRealRole;
public BusinessHandler(IBusiness mRealRole) {
super();
this.mRealRole = mRealRole;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Additional evaluation before purchase
System.out.println("Additional evaluation before purchase...");
// Specific business logic of the real role
method.invoke(mRealRole, args);
// Satisfaction survey after purchase
System.out.println("Satisfaction survey after purchase...");
return null;
}
}
Use the static method newProxyInstance() of Proxy to generate the proxy object, as follows:
/**
* Test JDK's dynamic proxy
*/
public class DynamicProxyClient {
public static void main(String[] args) {
// Create the real role
IBusiness mRealRole = new RealRole();
// Create the handler interface
InvocationHandler handler = new BusinessHandler(mRealRole);
/**
* Get the proxy object corresponding to the proxy role
* newProxyInstance parameters (class loader, interfaces implemented by the dynamically generated proxy class, invocation handler of the proxy object)
*/
IBusiness proxy = (IBusiness) Proxy.newProxyInstance(handler.getClass().getClassLoader(), mRealRole.getClass().getInterfaces(), handler);
// The proxy role helps you buy things
proxy.buy();
}
}
The result of the above code execution is as follows:
Additional evaluation before purchase...
I want to buy something
Satisfaction survey after purchase...
Learning static proxy helps with the understanding of dynamic proxy. The main difference between the two is that dynamic proxy does not require writing proxy classes. The corresponding proxy class will be dynamically generated during the code execution process. Of course, the generated proxy class also implements the interface corresponding to the abstract role. At the same time, the invocation handler of the proxy role will take over the specific business logic. This is the end of the explanation about static proxy and dynamic proxy.