代理模式
代理模式是一种常用的Java设计模式,代理模式是指处理一个业务逻辑时,通过代理的方式完成。代理模式中包含被代理方(委托方)和代理方,委托方委托代理帮助他完成某些工作。在所有的代理模式中,委托方和代理方都有一个共性,即双方都具备完成需求的能力。
Java程序中如何描述这个关系?
将类所具备的能力封装成接口,Java委托类和代理类需要实现同一个接口。
代理类和委托类是通过依赖注入进行关联,在设计程序时需要将委托类定义为代理类的成员变量
1、所有的操作全部在代理类中完成
2、核心业务操作还是由委托类本身完成
3、代理类完成其他非核心工作
4、委托类需要作为成员变量注入到代理类中
代理模式可以分为:静态代理和动态代理
二者区别:静态代理需要提前编写好代理类的代码,在编译期间代理类的class文件就已经生成了,代码是写死的。动态代理是指编译期间代理类的代码不确定,而是在程序运行期间根据代码的指示动态生成的,代码不是写死的,而是灵活变通的。静态代理和反射没有任何关系,动态代理是需要通过反射机制来实现灵活性的。
静态代理
定义一个手机接口类,让其子类实现卖手机功能,手机代理厂商卖不同的手机。
public interface Phone {
public String salePhone();
}
public class IPhone implements Phone {
@Override
public String salePhone() {
return "卖苹果手机";
}
}
public class HuaWei implements Phone {
@Override
public String salePhone() {
return "卖华为手机";
}
}
public class PhoneProxy implements Phone{
private Phone phone;
public PhoneProxy(Phone phone) {
this.phone = phone;
}
@Override
public String salePhone() {
System.out.println("启动卖手机代理模式");
return this.phone.salePhone();
}
}
public static void main(String[] args) {
PhoneProxy phoneProxy1 = new PhoneProxy(new IPhone());
System.out.println(phoneProxy1.salePhone());
PhoneProxy phoneProxy2 = new PhoneProxy(new HuaWei());
System.out.println(phoneProxy2.salePhone());
}
此厂商只能代理卖手机的功能,不能代理其他产品,如果需要代理其他产品,则必须修改代码,扩展性差。
动态代理
代码完全不需要修改,可以完成代理机制,只需要写一个辅助类,辅助动态代理机制动态生成真正的代理类。就是动态生成代理类的功能。
Java中如何让一个类具备某种功能?
Java中用接口定义功能,只需要让目标类实现该接口,目标类就具备了相应的功能。
public class MyInvocationHandler implements InvocationHandler {
// 记录委托对象
private Object object;
// 传入委托对象
// 返回动态创建的代理对象
public Object bind(Object o){
this.object = o;
// newProxyInstance需要传入3个参数
// ClassLoader loader, 当前类加载器
// Class<?>[] interfaces, 实现类的接口
// InvocationHandler h 当前InvocationHandler实例
return Proxy.newProxyInstance(MyInvocationHandler.class.getClassLoader(),object.getClass().getInterfaces(),this);
}
// invoke通过反射机制来完成方法调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start proxy...");
// 委托对象调用核心业务方法
return method.invoke(object,args);
}
}
测试:
Car car = new BMW();
Phone phone = new HuaWei();
MyInvocationHandler invocationHandler = new MyInvocationHandler();
Car bind1 = (Car)invocationHandler.bind(car);
System.out.println(bind1.saleCar());
Phone bind2 = (Phone)invocationHandler.bind(phone);
System.out.println(bind2.salePhone());
实现了2种产品的代理。