代理模式Proxy

原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11401233.html

 

1. 定义
为其他对象提供一种代理以控制这个对象的访问。

 

2. 结构图

 

Proxy:代理对象。通常具有如下功能。

  • 实现与具体的目标对象一样的接口,这样就可以使用代理来代替具体的目标对象。
  • 保存一个指向具体目标对象的引用,可以在需要的时候调用具体的目标对象。
  • 可以控制对具体目标对象的访问,并可以负责创建和删除它。

Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何使用具体目标对象的地方使用代理对象。
RealSubject:具体的目标对象,真正实现目标接口要求的功能。

 

3. 本质
代理模式的本质:控制对象访问。 

 

4. Code Demo

Subject.java

1 package org.fool.dp.proxy;
2 
3 public interface Subject {
4     void request();
5 }

RealSubject.java

1 package org.fool.dp.proxy;
2 
3 public class RealSubject implements Subject {
4     @Override
5     public void request() {
6         System.out.println("real subject invoked...");
7     }
8 }

ProxySubject.java

 1 package org.fool.dp.proxy;
 2 
 3 public class ProxySubject implements Subject {
 4     private RealSubject realSubject;
 5 
 6     @Override
 7     public void request() {
 8         System.out.println("proxy start...");
 9 
10         if (null == realSubject) {
11             realSubject = new RealSubject();
12         }
13 
14         realSubject.request();
15 
16         System.out.println("proxy end...");
17     }
18 }

Client.java

1 package org.fool.dp.proxy;
2 
3 public class Client {
4     public static void main(String[] args) {
5         Subject proxySubject = new ProxySubject();
6         proxySubject.request();
7     }
8 }

 

5. 动态代理

Java对代理模式提供了内建的支持,在java.lang.reflect包下面,提供了一个Proxy的类和一个InvocationHandler的接口。
通常把前面自己实现的代理模式称为Java的静态代理。这种实现方式有一个较大的缺点,就是如果Subject接口发生变化,那么代理类和具体的目标实现都要变化,不是很灵活。而使用Java内建的对代理模式支持的功能来实现则没有这个问题。
通常把使用Java内建的对代理模式支持的功能来实现的代理称为Java的动态代理。动态代理跟静态代理相比,明显的变化是:静态代理实现的时候,在Subject接口上定义很多的方法,代理类里面自然也要实现很多方法;而动态代理实现的时候,虽然Subject接口上定义了很多方法,但是动态代理类始终只有一个invoke方法。这样,当Subject接口发生变化的时候,动态代理的接口就不需要跟着变化了。
Java的动态代理目前只能代理接口,基本的实现是依靠Java的反射机制和动态生成class的技术,来动态生成被代理的接口的实现对象。
代理模式在客户和被客户访问的对象之间,引入了一定程度的间接性,客户是直接使用代理,让代理来与被访问的对象进行交互。不同的代理类型,这种附加的间接性有不同的用途,也就具有不同的特点。

 

动态代理Demo

Subject.java

1 package org.fool.dp.dynamicproxy;
2 
3 public interface Subject {
4     void request();
5 }

RealSubject.java

1 package org.fool.dp.dynamicproxy;
2 
3 public class RealSubject implements Subject {
4     @Override
5     public void request() {
6         System.out.println("real subject invoked...");
7     }
8 }

DynamicSubject.java

 1 package org.fool.dp.dynamicproxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class DynamicSubject implements InvocationHandler {
 7     private Object subject;
 8 
 9     public DynamicSubject(Object subject) {
10         this.subject = subject;
11     }
12 
13     @Override
14     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
15         System.out.println("before calling: " + method);
16 
17         method.invoke(subject, args);
18 
19         System.out.println("after calling: " + method);
20 
21         return null;
22     }
23 }

Client.java

 1 package org.fool.dp.dynamicproxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Proxy;
 5 
 6 public class Client {
 7     public static void main(String[] args) {
 8         Subject realSubject = new RealSubject();
 9 
10         InvocationHandler handler = new DynamicSubject(realSubject);
11 
12         Class<? extends InvocationHandler> handlerClass = handler.getClass();
13 
14         Subject proxySubject = (Subject) Proxy.newProxyInstance(handlerClass.getClassLoader(),
15                 realSubject.getClass().getInterfaces(), handler);
16 
17         proxySubject.request();
18     }
19 }

 

posted @ 2019-08-23 17:04  李白与酒  阅读(229)  评论(0编辑  收藏  举报