由于某些原因,需要给对象提供一个代理以控制对该对象的访问,这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介
Java中的代理按照代理类生成时机不同又分为静态代理和动态代理,静态代理类在编译期就生成,而动态代理代理类则是在java运行时动态生成,动态代理又有JDK代理CGLib代理两种
结构
代理模式分为三种角色
抽象主题类:通过接口或抽象类来声明真实主题和代理对象实现的业务方法
真实主题类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象
代理类: 提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能
优点:
- 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
- 代理对象可以扩展目标对象的功能;
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性
缺点:
- 代理模式会造成系统设计中类的数量增加
- 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
- 增加了系统的复杂度;
适用场景
远程代理
这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
防火墙代理
智能指引
主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它。
保护代理
控制对一个用户的访问,控制权限
案例
先来一个简单的栗子在网络不发达的时候,买火车票只能去火车站买,然后目前我们都是在网上买,这其实就是一个代理的模式,当然目前还有中介租房,婚介,等等,
/**
* 卖票功能接口
*/
public interface Sellfickets {
void sell();
}
/**
* 火车站类
*/
public class TrainStation implements Sellfickets {
@Override
public void sell() {
System.out.println("火车站卖票");
}
}
/**
* 代理类
*/
public class ProxyPoint implements Sellfickets {
//声明火车站类对象 利用聚合,而非继承
private TrainStation trainStation=new TrainStation();
@Override
public void sell() {
System.out.println("收取服务费");
trainStation.sell();
}
}
//测试
public class Test {
public static void main(String[] args) {
ProxyPoint proxyPoint=new ProxyPoint();
proxyPoint.sell();
}
}
根据代理的创建时期,代理模式分为静态代理和动态代理
- 静态:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
- 动态:在程序运行时,运用反射机制动态创建而成