一、设计模式之代理设计
代理设计是在Java开发中使用较多的一种设计模式,所谓的代理设计模式就是指一个代理主体操作真实主体,真实主体操作具体业务,代理主体负责给具体业务添砖加瓦。
就好比在生活中你有一套房子想要出租(你=真实主体),你找了房产中介(中介=代理主体)。真实主体负责提供房屋和收钱,代理主体负责带客户看房 、扣除手续费。租客只管租房子和付款,至于谁提供的房子并不关心。
我们发现,只需要定义一个租赁的接口,真实主体与代理主体都可以实现此接口,然后再由代理主体操作真实主体即可,上面的要求可以形成如下的代码:
1. 定义租赁接口
java
package com.javabasic.proxy;
/**
* 定义抽象接口
*/
public interface House {
/**
* 定义抽象方法 租赁
*/
void rent();
}
2. 定义真实主体 - 房东
java
package com.javabasic.proxy;
/**
* 定义真实主体 房东
*/
public class Owner implements House{
@Override
public void rent() {
System.out.println("房东提供房子,收取租金200元/月");
}
}
3. 定义代理主体 - 中介
java
package com.javabasic.proxy;
/**
* 定义代理主体 中介
*/
public class Agent implements House{
// 接收真实主体 房东
private House house;
/**
* 通过构造方法,让中介与房东之间产生联系。
* 根据Java动态绑定机制,House运行时的真实类型是房东类型,就可以获取到房东的出租行为。
* @param house
*/
public Agent(House house){
this.house = house;
}
/**
* 中介对房东出租业务进行增强
*/
@Override
public void rent() {
rentBefore();
house.rent(); // 房东 出租
rentAfter();
}
private void rentBefore(){
System.out.println("中介负责寻找租客、带看、保存租客信息、签合同、收取租金。");
}
private void rentAfter(){
System.out.println("中介负责租客退租后的清扫工作。");
}
}
4. 主程序 中介出租房屋
二、动态代理
上面讲解的代理机制的操作,属于静态代理,因为每一个代理类只能为一个接口服务,这样程序开发中必然会产生过多的代理类。最好的做法是可以通过一个代理类完成全部的代理功能
,那么此时就必须使用动态代理功能。
Java 中想要实现动态代理的机制,则需要java.lang.reflect.InvocationHandler接口
和 java.lang.reflect.Proxy类
的支持。
InvocationHandler接口的定义如下:
java
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类。
java
/*
ClassLoader loader : 类加载器
Class<?>[] interfaces : 得到真实类实现的全部接口
InvocationHandler h : 得到InvocationHandler子类实例
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
...
}
房屋租赁代码修改如下 :
1. 需要房东实现租赁的接口
java
public interface House {
/**
* 定义抽象方法 租赁
*/
void rent();
}
public class Owner implements House{
@Override
public void rent() {
System.out.println("房东提供房子,收取租金200元/月");
}
}
2. 创建代理类(InvocationHandler / Proxy)
java
package com.javabasic.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Agent2 implements InvocationHandler {
// 接收真实主体
private Object obj;
// 对外提供绑定真实主体方法
public Object bind(Object obj){
this.obj = obj;
// 通过真实对象创建代理对象并返回给调用者。
/*
Proxy.newProxyInstance : 三个参数
类加载器 : this.obj.getClass().getClassLoader()
真实类型实现的所有接口 : this.obj.getClass().getInterfaces()
代理类 : this
return 代理对象
*/
Object object = Proxy.newProxyInstance(this.obj.getClass().getClassLoader(),
this.obj.getClass().getInterfaces(), this);
System.out.println("bind之后object真实类型 = " + object.getClass().getName());
return object;
}
/**
* 代理类会执行的方法。
* @param proxy 代理主体
* @param method 调用的方法
* @param args 方法的参数
*
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy真实类型 = " + proxy.getClass().getName());
rentBefore();
method.invoke(this.obj, args); // 通过反射执行真实主体方法
rentAfter();
return null;
}
private void rentBefore(){
System.out.println("中介负责寻找租客、带看、保存租客信息、签合同、收取租金。");
}
private void rentAfter(){
System.out.println("中介负责租客退租后的清扫工作。");
}
}