代理模式
什么是代理模式?
代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:
为什么要用代理模式?
中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
代理概念:
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);
}
}