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 码的连衣裙!
精美包装,快递一条龙服务。终身保修!

原文地址:https://www.cnblogs.com/wlwl/p/9468348.html