Proxy Pattern _ supplement
Preface: the internal principle, role, and implementation of remote proxy are explained in detail in the previous blog. This article is just a supplement to its content and introduces other proxies. virtual proxy first defines the role of virtual Proxy: before a large object is created, virtual proxy is used to replace a large object (this ensures that a large object is created only when necessary, avoid resource waste. We may often use virtual proxies, but don't know them. For example: in our program, operations that consume resources such as intensive computing or getting a large amount of data from the server usually display the default information first, or an animation indicates that our program is still working hard. After the operation is completed, the information obtained is displayed, and the idea of virtual proxy is used, only the virtual proxy separates all the work waiting for the operation to be completed and encapsulates it into a virtual proxy object, objects that directly interact with the customer are virtual proxies rather than objects that actually do things. After receiving a request from the customer, the virtual proxy does the following: if the actual object does not exist (not created or not created yet) the customer request is recorded and the default information is displayed. After the actual object is created, the request is passed to the real If the actual object already exists, the client request is directly delegated to the actual object. Before the actual object does not return the operation result, the proxy object displays the default information (or performs the default processing) after the operation result is obtained, it is directly transmitted to the customer (yes, the proxy task is "Submit" and "Connect"). Since it is a proxy, it must be disguised as an actual object, the customer cannot discover the existence of the Proxy, so the class diagram of the virtual Proxy is as follows: the Client holds a virtual Proxy object Proxy, and the Proxy holds a specific service object MyService, and more importantly: the virtual Proxy and the specific Service MyService both expand from the Service interface, so the Proxy and the actual object have the same behavior, the customer will not find the existence of the Proxy. protection proxy protection protects the Proxy from playing the role of the broker (not everyone can contact the stars behind me. You can only contact me and transfer it to you after I confirm that you are not a bad person ..) In other words, the protection proxy provides access control for the actual object and ensures that only valid callers can get service implementation. The class diagram is exactly the same as the preceding virtual proxy, it's just that the Proxy has an additional responsibility to determine the caller's permissions (Do you find anything? We seem to be able to combine multiple proxies. Of course, such proxies no longer meet the single responsibility principle of the class, but it doesn't matter, we can create a proxy to manage a series of proxies ..) In fact, Java APIs provide support for the Proxy mode (Dynamic Proxy) the dynamic Proxy provided by Java is dynamically reflected in the Proxy class (yes, it is a class, not an object) it is created only at runtime. We cannot directly modify the internal implementation of Proxy, but we can use InvocationHandler to tell the Proxy how to use dynamic Proxy to protect Proxy. The basic idea is to create multiple proxies, different proxies indicate the services corresponding to callers with different permissions. So let's design a scenario and try to use dynamic proxies to protect the Proxy: blog post thumb up mechanism: You can like others' blog posts, you cannot like your own blog posts, but it is relatively simple for bloggers and visitors to see the number of liked posts, but it is enough to explain the problem. The following describes how to simulate the implementation of ------- first, you must have BlogUser: package ProxyPattern. protectionProxy;/*** defines the blog User interface * @ author ayqy */public interface BlogUser {public void support (); public int getSupportCount ();} also has ConcreteUser, the implementation process is relatively simple. We will not start to create a dynamic proxy here. There are two types of permissions: bloggers and tourists. Therefore, we need at least two different dynamic proxies: AuthorHandler: package ProxyPattern. protectionProxy; import java. lang. reflect. invocationHandler; import java. lang. reflect. invocationTargetException; import java. lang. reflect. method;/*** implement InvocationHandler * @ author ayqy */public class AuthorHandler implements InvocationHandler {BlogUser user; public AuthorHandler (BlogUser user) {this. user = user ;}@ Override public Object invoke (Object proxy, Method method, Object [] args) throws IllegalAccessException {// declares an invalid access exception. try {/* if the blogger wants to view the number of likes, delegate the user to the caller for specific operations */if (method. getName (). equals ("getSupportCount") {return method. invoke (user, args);}/* if you like it, an exception is thrown, indicating that the request is rejected */if (method. getName (). equals ("support") {throw new IllegalAccessException () ;}} catch (InvocationTargetException e) {// TODO Auto-generated catch block e. printStackTrace ();} return null; // if other methods are called, directly ignore}. Similarly, we also need to implement VisitorHandler with multiple proxies. We also need to implement proxy proxies, that is, protection proxy (returns a corresponding dynamic proxy according to the caller's permission) ProtectionProxy: package ProxyPattern. protectionProxy; import java. lang. reflect. proxy; /*** implement protection proxy * @ author ayqy */public class ProtectionProxy {/*** @ param user caller * @ return proxy */public BlogUser getAuthorProxy (BlogUser user) {return (BlogUser) Proxy. newProxyInstance (user. getClass (). getClassLoader (), user. getClass (). getInterfaces (), new AuthorHandler (user);}/*** @ param user caller * @ return visitor's proxy */public BlogUser getVisitorProxy (BlogUser user) {return (BlogUser) Proxy. newProxyInstance (user. getClass (). getClassLoader (), user. getClass (). getInterfaces (), new VisitorHandler (user);}/* Insert the method to generate other proxies here */}. This is enough for a simple test: package ProxyPattern. protectionProxy;/*** implementation Test class * @ author ayqy */public class Test {public static void main (String [] args) {// create protection proxy ProtectionProxy = new ProtectionProxy (); System. out. println ("master part:"); // create the proxy BlogUser authorProxy = proxy for the master. getAuthorProxy (new ConcreteUser (); System. out. println ("Main blog views total number of likes"); System. out. println ("liked" + authorProxy. getSupportCount () + ""); // you can give yourself a thumbs up on the System. out. println ("blog thumb ups"); try {authorProxy. support ();} catch (Exception e) {System. out. println ("thumbs up failed, you cannot like yourself");} System. out. println ("like, liked" + authorProxy. getSupportCount () + "times"); System. out. println ("\ n visitor part:"); // create the proxy BlogUser vistorProxy = proxy for the visitor. getVisitorProxy (new ConcreteUser (); System. out. println ("visitors want to view the total number of likes"); System. out. println ("liked" + vistorProxy. getSupportCount () + ""); // you can give yourself a thumbs up on the System. out. println ("visitors want to give the bloggers a thumbs up"); try {vistorProxy. support ();} catch (Exception e) {System. out. println ("thumb up failed, unknown reason");} System. out. println ("liked, liked" + vistorProxy. getSupportCount () + "times ");}}