一.定义
- 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
代理在结构上类似装饰着,但目的不同,装饰者模式为对象加上行为,而代理则是控制访问 代理为另一个对象提供代表,以便客户对对象的访问
二.作用
- 职责清晰真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理
完成一件事务,附带的结果就是编程简洁清晰。 - 高扩展性
三.案例
本章将讲解普通代理和动态代理两种代理方式
- 普通代理
大学毕业之后大学生们就开始前往不同的城市参加工作,有些公司提供住房还好,但是这种可能性基本不大,于是乎就得考虑住房问题,这个时候市场上就出现了房屋中介商,专门解决这样类似的问题。下面是简单的示意图
IHouse接口有两个方法房屋位置和房屋大小
public interface IHouse {
//位置
void location(String address);
//大小
void size(int size);
}
实现类House,这个类主要用来实现具体的业务逻辑,这里只打印这些信息,
public class House implements IHouse {
@Override
public void location(String address) {
System.out.println(address);
}
@Override
public void size(int size) {
System.out.println(size+"平方");
}
}
下面是代理模式的核心代理类,通过构造函数定义一个需要被代理的对象,同时它还可以具备自己的方法,作为一个房屋代理者,它还可以告诉你租房所需的费用
public class HomeProxy implements IHouse {
private IHouse house;
//构造函数定义一个租房
public HomeProxy() {
this.house = new House();
}
@Override
public void location(String address) {
this.house.location(address);
}
@Override
public void size(int size) {
this.house.size(size);
cost(size);
}
//合计
public void cost(int size) {
System.out.println(size * 5 + tip(size)+"$");
}
//中介费
public double tip(int size) {
return size * 5 * 0.35;
}
}
我们模拟一下租房的过程,如下所示:
public static void main(String[] args) {
//创建一个房屋中介商
IHouse proxy = new HomeProxy(house);
//租房的位置
proxy.location("上海");
//租房的大小
proxy.size(100);
}
运行结果如下:
上海
100平方
675.0$
这种模式下通过构造函数定义一个代理对象,进行代理。调用者只需要知道代理类是谁就可以了,结构更加清晰,屏蔽了
真实角色的变更对高层模块的影响,真是角色只需要实现接口,实现具体的业务逻辑,想怎么改就怎么改,提高了扩展性
- 动态代理
动态代理需要实现InvocationHandler接口产生一个代理对象,InvocationHandler是JDK本身就提供好的的动态代理接口,这里用HomeIH去实现这个接口
public class HomeIH implements InvocationHandler {
//被代理的实例
Object obj;
//我要代理谁
public HomeIH(Object _obj) {
this.obj = _obj;
}
//调用被代理的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//方法执行之前
System.out.println("before " + method.getName());
//执行被代理的方法
Object result = method.invoke(this.obj, args);
return result;
}
}
这样写之后所有方法都由该Handler来进行处理,所有被代理的方法都由invoke方法去执行,invoke的三个参数分别为proxy(代理对象 ),method(被调用方法),args(被调用方法的参数)还是延续上面的代码,只需将main函数修改如下
public static void main(String[] args) {
//被代理实例
IHouse house = new House();
//通过构造函数传入到Handler中
HomeIH handler = new HomeIH(house);
//动态产生一个代理者
IHouse proxy = (IHouse) Proxy.newProxyInstance(house.getClass().getClassLoader(),new Class[]{IHouse.class},handler);
//租房的位置
proxy.location("上海");
//租房的大小
proxy.size(100);
}
运行之后看结果:
before location
上海
before size
100平方
看到没这就是动态代理,还是通过代理去租房,和普通代理的区别就是,动态代理不用创建代理类,不用实现方法接口,而且更加的灵活,更加的具备扩展性 ,当然,JDK的动态代理有一个需要注意的地方,这里的每个委托类都必须是要有接口的,如果你问我,没有实现接口能不能被代理,我说能
四.总结
代理类不仅仅是一个隔离客户端和委托类的中介。我们还可以借助代理来在增加一些功能,而不需要修改原有代码,完美的体现了开闭原则。
真正的业务功能还是有被代理来实现,但是在实现业务类之前的一些公共服务,或者之后的服务。我们可以通过代理模式来实现