天天看点

动态代理模式【大话设计模式】

代理模式

什么是代理模式?

代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:

为什么要用代理模式?

中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。

开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

代理概念:

1.真实对象:被代理的对象

2.代理对象:代理真实对象的对象

3.代理模式:代理对象代理真实对象,达到增强真实对象功能的的目的。

两种代理:

1.静态代理:有一个类文件描述代理模式

2.动态代理:在内存中形成代理类。

实现步骤:

1.代理对象和真实对象实现相同的接口

2.代理对象=Proxy.newInstance();

3.使用代理对象

代码案例(动态代理卖联想电脑)

真实类

package 动态代理;
/*
 * 真实类
 */
public class Lenovo implements SaleCompeter{

	@Override
	public String sale(double money) {
		System.out.println("花了"+money+"买了一台电脑");
		return "联想电脑";
	}

	@Override
	public void show() {
		
	}
}

           

接口

package 动态代理;

public interface SaleCompeter {
	public String sale(double money);
	
	public void show(); 
}

           

动态代理的步骤(固定写法)

package 动态代理;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理步骤
 */
public class ProxyTest {
    public static void main(String[] args) {
        //创建真实对象
        Lenovo lenovo=new Lenovo();

        //动态代理增强对象
        /*
           三个参数
              1.类加载器:真实对象.getClass().getClassLoader()
              2.接口数组:真实对象.getClass().getInterfaces()
              3.处理器:new InvocationHandler()

         */
        SaleCompeter proxy_lenovo = (SaleCompeter) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
            /*
               代理逻辑编写的方法,代理对象调用的所有方法都会触发该方法执行
                  参数:
                     1.proxy 代理对象
                     2.method 代理对象调用的方法,被封装为对象。
                     3.args 代理对象调用方法时传递的实际参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //System.out.println("代理对象实现的方法");
                //判断是否是sale方法
                if (method.getName().equals("sale")){
                    //1.增强参数
                    double money=(double)args[0];
                    money=money*0.85;
                    System.out.println("专车接");
                    //使用真实对象调用该方法
                    String  obj = (String) method.invoke(lenovo, money);
                    System.out.println("免费送货");
                    //增强返回值
                    return obj+"鼠标垫";
                } else {
                    Object obj = method.invoke(lenovo, args);
                    return obj;
                }
            }
        });

        //调用方法
        String competer = proxy_lenovo.sale(8000);
        System.out.println(competer);
    }
}