JDK动态代理
案例:我要定制一双鞋,势必要自己四处奔波找厂商,要对鞋的大小,款式,材料等繁琐的小事的操心,然后跟鞋厂对接好完之后,我又要过去验货,最后才能带回家。这样买鞋所花的时间成本肯定是不划算的,要是有一个提供代理服务的中间人就好了。
编写代理模式有3点必须遵从:
1.代理对象必须包含真实的对象
2.必须和真实对象实现同一个接口
3.必须提供更多的功能 (代理的目的不就是为了提供更多的服务吗)
案例编写:
一:创建被代理对象
/** * 1. 接口, 描述了服务提供者的行为 */ public interface A_ShoesFactory { // 订制鞋子。 void saleShoes(int size); }
二:创建这个接口的具体实现
/** * 1. 真正提供服务的类,销售鞋子的厂商。 */ public class A_ShoesFactoryImpl implements A_ShoesFactory{ @Override public void saleShoes(int size) { System.out.println("为你量身定制了一双: "+size+" 码的鞋子!"); } }
三:创建代理对象
/** * 【静态代理类】 * 代理对象, * 必须包含真实的对象, * 必须和真实对象实现同一个接口, * 并且提供更多的功能。 */ public class Service_Static implements A_ShoesFactory{ //被包含的真实对象 private A_ShoesFactory factory; public Service_Static(A_ShoesFactory factory) { super(); this.factory = factory; } @Override public void saleShoes(int size) { doSomeThingBeFore();//前置增强 factory.saleShoes(size); doSomeThingEnd();//后置增强 } //售前任务 private void doSomeThingBeFore(){ System.out.println("根据您的需求,进行市场调研和产品分析!"); } //售后任务 private void doSomeThingEnd(){ System.out.println("精美包装,快递一条龙服务。终身保修!"); } }
四: 创建客户端(测试)
public class Client { //【静态代理测试】 public static void main(String[] args) { //1. 从前有一个售卖鞋子的厂商 A_ShoesFactory factory = new A_ShoesFactoryImpl(); //2. 代购商来帮你代购这个产品 Service_Static wl = new Service_Static(factory); //3. 根据你的需求,定制了一双40码的AJ运动鞋。 wl.saleShoes(40); } } =================================== 【控制台输出结果】 根据您的需求,进行市场调研和产品分析! 为你量身定制了一双: 40 码的鞋子! 精美包装,快递一条龙服务。终身保修!
看完上面的场景我们对代理模式有了个大概地认识:
优点:1、职责清晰。 2、高扩展性。 3、 对服务者和消费者的关系解耦,保护了服务者对象,解决了直接访问目标的不必要复杂性。
缺点:需要在客户端和真实主题之间增加了代理对象,实现起来会稍微有些麻烦。
这仅仅只是一个静态代理模式。如果此时代理商要扩展业务,不仅仅代理鞋子还要代理衣服,那怎么办?
如果要代理衣服,那么:
1. 按照上面的一、二步,先写个衣服的接口和实现类。
2. 代理对象再实现一个衣服,重写它里面的具体方法。
No No No,这仅仅是代理2个产品,就这么麻烦,如果我要是代理几千的产品,那代理对象岂不是要实现几千个接口?其实这种情况严重的违反了设计模式中的【开闭原则】 对扩展开放,对修改关闭。我们的代理对象不应该管具体代理的是什么商品,而是不管任何商品我都应该采用同一个方法去代理。
不多说了,继续上代码。
一:首先按照上面的步骤,编写一个衣服的接口和实现类。
/** * 1. 接口, 描述了服务提供者的行为 */ public interface A_ClothesFactory { // 订制衣服。 void saleClothes(String size); }
/** * 1. 真正提供服务的类,销售衣服的厂商。。 */ public class A_ClothesFactoryImpl implements A_ClothesFactory{ @Override public void saleClothes(String size) { System.out.println("为你量身定制了一件: "+size+" 码的连衣裙!"); } }
二: 编写JDK动态代理类
/** * 【JDK动态代理类】 * 原理: 通过反射获取被代理对象的实例,将生成后的代理对象强制转换为接口。 */ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Servcice_dongtai implements InvocationHandler{ //被代理的对象是个Object类型的 private Object factory; public Object getFactory() { return factory; } public void setFactory(Object factory) { this.factory = factory; } public Object getProxyInstance(){ // arg0被代理的真实对象 arg1被代理接口 arg2代理对象 return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { doSomeThingBeFore();//前置增强 Object obj = method.invoke(factory, args); doSomeThingEnd();//后置增强 return obj; } //售前任务 private void doSomeThingBeFore(){ System.out.println("根据您的需求,进行市场调研和产品分析!"); } //售后任务 private void doSomeThingEnd(){ System.out.println("精美包装,快递一条龙服务。终身保修!"); } }
三:编写客户端 (测试)
public class Client { // 【静态代理测试】 // public static void main(String[] args) { // //1. 从前有一个售卖鞋子的厂商 // A_ShoesFactory factory = new A_ShoesFactoryImpl(); // //2. 代购商来帮你代购这个产品 // Service_Static wl = new Service_Static(factory); // //3. 根据你的需求,定制了一双40码的AJ运动鞋。 // wl.saleShoes(40); // } // 【动态代理测试】 public static void main(String[] args) { A_ShoesFactory shoes = new A_ShoesFactoryImpl(); A_ClothesFactory clothes = new A_ClothesFactoryImpl(); Servcice_dongtai service = new Servcice_dongtai(); service.setFactory(shoes); A_ShoesFactory a = (A_ShoesFactory)service.getProxyInstance(); a.saleShoes(40); System.out.println("-------------------"); service.setFactory(clothes); A_ClothesFactory b = (A_ClothesFactory)service.getProxyInstance(); b.saleClothes("S"); } }
===================================
【控制台输出结果】
根据您的需求,进行市场调研和产品分析!
为你量身定制了一双: 40 码的鞋子!
精美包装,快递一条龙服务。终身保修!
-------------------
根据您的需求,进行市场调研和产品分析!
为你量身定制了一件: S 码的连衣裙!
精美包装,快递一条龙服务。终身保修!