【代理模式】

代理模式介绍


代理模式的好处:

●可以是真实的角色的操作更加纯粹!不用去关注一些公共的业务
●公关也就交个代理角色!实现了业务的分工
●公共业务发生扩展的时候,方便集中管理
代理模式的缺点:
●一个真实角色就会产生一个代理角色;代码两会翻倍,开发效率会变低

静态代理

静态代理代码和理解:
可以将这个类理解为一个房东
* 房东因为生病急需用钱所以想将自己的房子快速租出去
* 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院
* 所以将租房的工作代理给中介去执行

/**
 * 一个租房的接口
 * 该接口具有租房的方法(行为)
 */
public interface IRentHouse {
    void rentHouse();
}

代理类:IntermediaryProxy 

/**-
 * 理解:这个类类似中介
 * 我也可以进行租房的操作,我可以代理房东进行租房
 * 我可不白干,需要点中介费
 */
public class IntermediaryProxy implements IRentHouse{
    private IRentHouse iRent ;

    public IntermediaryProxy(IRentHouse IRentHouse)
    {
        this.iRent = IRentHouse;
    }

    @Override
    public void rentHouse()
    {
        System.out.println("交1000中介费~~~我今天内将房子租出去");

        iRent.rentHouse();
        System.out.println("我把房子租出去了:给你钱,中介费给你扣了-1000");
    }
}

被代理类:RentHouse 

/**
 * 代理模式
 * 可以将这个类理解为一个房东
 * 房东因为生病急需用钱所以想将自己的房子快速租出去
 * 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院
 * 所以将租房的工作代理给中介去执行()
 *
 */
public class RentHouse implements IRentHouse{
    @Override
    public void rentHouse()
    {
        System.out.println("实现租房");
    }
}
public class StaticTestMain {
    public static void main(String[] args)
    {
        //模拟一个房东
        RentHouse landlord = new RentHouse();

        //模拟一个中介(代理将房租出去)
        IntermediaryProxy intermediaryProxy = new IntermediaryProxy(landlord);
        //执行租房的行为
        intermediaryProxy.rentHouse();
    }
}

动态代理

推荐视频:

狂神说的视频,对于动态代理讲解的很详细

记录一篇好的文章
java动态代理中的invoke方法是如何被自动调用的_zcc_0015的博客-CSDN博客

动态代理分为两大类:基于接口的动态代理,基于类的动态代理

  • 基于接口--JDK动态代理
  • 基于类的--cglib
  • java字节码实现:javasist

以下为JDK动态代理

最重要的两个类:Proxy和InvocationHandler

Proxy的作用:提供创建动态代理类的和实例的静态方法

InvocationHandler:处理代理实例,并返回结果的

动态代理的好处:

  • 可以是真实的角色的操作更加纯粹!不用去关注一些公共的业务
  • 公关也就交个代理角色!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理
  • 一个动态代理类代理的是一个接口,一般对应着一类业务
  • 一个动态代理类可以代理多个类,只要实现了接口
/**
 * 一个租房的接口
 * 该接口具有租房的方法(行为)
 */
public interface IRentHouse {
    void rentHouse();
    void needAgent(double money);
}
/**
 * 代理模式
 * 可以将这个类理解为一个房东
 * 房东因为生病急需用钱所以想将自己的房子快速租出去
 * 但是,房东的资源比较少,想要及时将房子租出去需要花费时间,而自己需要马上去医院
 * 所以将租房的工作代理给中介去执行()
 *
 */
public class RentHouse implements IRentHouse {
    @Override
    public void rentHouse()
    {

        System.out.println("房东:支付的房租为:1000元!");
        System.out.println("实现租房");
    }

    @Override
    public void needAgent(double money)
    {
        System.out.println("房东内心os:没办法只能请中介");
        System.out.println("通过中介,获取的房租为:" + money+"元");
    }

}

public static Object newProxyInstance(ClassLoader loader,

Class[] interfaces,

InvocationHandler h)

参数一:用于指定用哪个类加载器,去加载生成的代理类,一般为被代理的对象

参数二:指定接口,这些接口用指定生成的代理有哪些方法,通常也为被代理对象的接口

参数三:用来指定生成的代理对象要干什么事情

代理对象干什么事儿都由invoke()方法决定

官方的解释:处理代理实例,并且返回结果

public Object invoke(

Object proxy,

Method method,

Object[] args) throws Throwable

参数一:代理对象,注意是代理对象,不是被代理对象

参数二:代理类对象调用的方法,被封装为的方法对象。此方法也就作为了被代理类对象要调用的方法

参数三:代理对象调用方法时,传递的实际参数

代理类(使用动态代理实现): 

public class DybanucTestMain {
    public static void main(String[] args)
    {
        //模拟一个房东,被代理类
        RentHouse landlord = new RentHouse();
        //动态代理增强 landlord 对象
        /**
         *我用动态代理,就不需要自己新建IntermediaryProxy(中介)对象,直接使用
         *
         * 静态代理:有一个类文件来描述代理模式(此案例中就是IntermediaryProxy(中介)对象)
         * 动态代理:在内存中形成代理类
         *
         * 三个参数:
         *ClassLoader loader =  landlord.getClass().getClassLoader(), 类的加载器,是哪个需要代理的类,
          Class[] interfaces = landlord.getClass().getInterfaces(), 被代理类的实现的接口
          InvocationHandler h = new InvocationHandler() {}:当我们通过代理类的对象,调用方法时,会自动的调用如下的方法:invoke()
         */

        IRentHouse proxy_landlord = 
        (IRentHouse) Proxy.newProxyInstance(
            landlord.getClass().getClassLoader(), 
            landlord.getClass().getInterfaces(), 
             new InvocationHandler() {
            /**
             *
             *
             *主要是用来实现代理逻辑
             *
             *参数:proxy :代理对象
             *     method:代理类对象调用的方法,被封装为的对象。此方法也就作为了被代理类对象要调用的方法
             *     args :代理对象调用方法时,传递的实际参数
             
             *将被代理类要执行的方法a的功能就声明在invoke()中
             */
            @Override
            public Object invoke(
                Object proxy, 
                Method method, 
                Object[] args) throws Throwable
            {


                //使用真实对象调用该方法

                if(method.getName().equals("needAgent")){
                    System.out.println("中介:来来来。嘿嘿!找我帮你出租呀,今天就给你租出去了,但是要给我中介费5%");
                    double money = (double) args[0];
                    money = money * 0.95;
                    Object obj = method.invoke(landlord, money);
                    return obj;
                }else {
                    System.out.println("中介:你没让我帮你找,就不用中介费了");
                    Object obj = method.invoke(landlord, args);
                    return obj;
                }

            }
        });
        //模拟通过自己将房子租出去
        //        proxy_landlord.rentHouse();
        //通过代理对象进行调用方法
        proxy_landlord.needAgent(1000);
    }
}

你可能感兴趣的:(代理模式)