由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
代理(Proxy
)模式分为三种角色:
- 抽象主题(
Subject
)类: 通过接口或抽象类声明真实主题和代理对象实现的业务方法。 - 真实主题(
Real Subject
)类: 实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。 - 代理(
Proxy
)类 : 提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
抽象主题类
public interface SellTickets {
void sell();
}
真实主题类
public class TrainStation implements SellTickets{
@Override
public void sell() {
System.out.println("我是火车站,卖票");
}
}
代理类:最终还要向真实主题类进行沟通
像程序中的那样,代理可以多收5块钱,同样,在使用代理类的时候,可以对程序进行不同的业务需求改造,更符合需求
public class ProxyPoint implements SellTickets{
private TrainStation station = new TrainStation();
@Override
public void sell() {
System.out.println("我是代理点,代理火车站卖票,收费5元");
station.sell();
}
}
拓展:JDK
的动态代理(代码是黑马设计模式中的代码)
//代理工厂,用来创建代理对象
public class ProxyFactory {
private TrainStation station = new TrainStation();
public SellTickets getProxyObject() {
//使用Proxy获取代理对象
/*
newProxyInstance()方法参数说明:
ClassLoader loader : 类加载器,用于加载代理类,使用真实对象的类加载器即可
Class<?>[] interfaces : 真实对象所实现的接口,代理模式真实对象和代理对象实现相同的接口
InvocationHandler h : 代理对象的调用处理程序
*/
SellTickets sellTickets = (SellTickets) Proxy.newProxyInstance(station.getClass().getClassLoader(),
station.getClass().getInterfaces(),
new InvocationHandler() {
/*
InvocationHandler中invoke方法参数说明:
proxy : 代理对象
method : 对应于在代理对象上调用的接口方法的 Method 实例
args : 代理对象调用接口方法时传递的实际参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理点收取一些服务费用(JDK动态代理方式)");
//执行真实对象
Object result = method.invoke(station, args);
return result;
}
});
return sellTickets;
}
}