代理模式(Proxy Pattern)是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。在代理模式中,一个类代表另一个类的功能,我们创建具有现有对象的对象,以便向外界提供功能接口。
为什么要控制对于某个对象的访问呢? 举个例子: 有这样一个消耗大量系统资源的巨型对象, 你只是偶尔需要使用它, 并非总是需要。
增加中间层,关键代码实现与被代理类组合。
新建一个与原服务对象接口相同的代理类, 然后更新应用以将代理对象传递给所有原始对象客户端。 代理类接收到客户端请求后会创建实际的服务对象, 并将所有工作委派给它。
1、Windows 里面的快捷方式,连接到真正应用程序。
2、买车不是直接去造车厂而是4s店。
3、spring aop(面向切片编程)。
具体例子:
信用卡是银行账户的代理,银行账户则是一大捆现金的代理。 它们都实现了同样的接口,均可用于进行支付。消费者会非常满意,因为不必随身携带大量现金;商店老板同样会十分高兴,因为交易收入能以电子化的方式进入商店的银行账户中,无需担心存款时出现现金丢失或被抢劫的情况。
案例实现步骤
(1)创建一个接口,定义卖u盘的方法。
public interface UsbSell { // 厂家和商家都要实现的功能(卖U盘) float sell(int amount); }
(2)创建工厂类
// 厂家不接受用户的单独购买,需要商家代理销售 public class UsbFactory implements UsbSell { @Override public float sell(int amount) { return 85.0f * amount; // 出厂价 } }
(3)创建商家类(代理类)
public class TaoBao implements UsbSell { // 声明商家代理的具体是哪个厂家 private UsbSell factory = new UsbFactory(); @Override public float sell(int amount) { float price = factory.sell(amount); float finalPrice = price + 25; // 功能增强 System.out.println("某宝返还您5元优惠券!!!"); return finalPrice; // 售价 } }
改价格操作是不能被消费者访问和使用的,作用对象只能是商家(微商、实体商店等)。
(4)创建测试类(普通消费者)
public class shopMain { public static void main(String[] args) { TaoBao tb = new TaoBao(); float pay = tb.sell(3); System.out.println("您购买的U盘,淘宝售价: "+ pay + '元'); } }
输出结果:
3x 85+25 = 280,验算后无误。
含义: 依靠jdk的反射机制,创建对象的能力,创建的是代理类的对象,不需要我们创建代理类。
动态代理会在jdk运行期间,动态创建class字节码并加载到JVM内存中。实现方式常用的有两种:使用JDK代理,与通过CGLlB动态代理。
这部分需理解 java反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect里有三个类:InvocationHandler、Method、Proxy。
(1)创建接口
public interface UsbSell { float sell(int amount); }
(2)创建工厂类(目标类)
public class UsbFactory implements UsbSell { @Override public float sell(int amount) { return 85.0f * amount; // 出厂价 } }
(3)创建InvocationHandler接口的实现类
//必须实现InvocationHandler接口,完成代理类的功能(调用目标方法、功能增强) public class MySellHandler implements InvocationHandler { private Object target = null; //动态代理的目标对象是动态传入的,传谁就给谁创建代理 public MySellHandler(Object target){ this.target = target; } //args代表接口中sell方法的参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object res = null; res = method.invoke(target,args); if(res!=null){ Float price = (Float)res; price = price+25; res = price; } System.out.println("某宝返还您5元优惠券!!!"); return res; } }
(4)编写测试类
public class Test { public static void main(String[] args) { //创建目标对象 UsbSell usbFactory = new UsbFactory(); //创建invocationHandler对象 InvocationHandler invocationHandler = new MySellHandler(usbFactory); //创建代理对象 UsbSell proxy= (UsbSell) Proxy.newProxyInstance( usbFactory.getClass().getClassLoader(), usbFactory.getClass().getInterfaces(), invocationHandler ); System.out.println("您购买的U盘,淘宝售价:"+ proxy.sell(100) + '元'); } }
输出结果:
与静态代理不同的是,我们不再需要每个工厂的具体实现类(如TaoBao.java) 。添加方法时,只需修改接口和目标类两个文件,客户类(Test.java)使用Proxy对象调用即可。注意jdk的动态代理必须有接口,目标类一定要实现该接口。
参考:设计模式(代理模式) | 代理设计模式