代理模式: 为其他对象提供一组代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式使用情形: 不希望用户直接访问该对象,而是提供一个特殊的对象以控制对当前对象的访问;如果一个对象加载需要很长时间可以提供一个代理对象去代替当前对象等。
代理模式分为: 静态代理和动态代理
代理模式中的角色:
抽象角色: 通过接口或抽象类声明真实角色实现的业务方法。
代理角色: 实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色: 实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
静态代理实例:
/**
* 抽象主题:需要买一个汽车
*/
public interface Car {
public void buyCar(); //需要买一个汽车
}
/**
* 顾客需要买一个车
* 汽车代理商通过先咨询顾客买车的价位款式等信息
* 帮顾客找到对应的汽车商 然后顾客自己付款给汽车商完成购买
* 最后由代理商三包服务把汽车送到顾客手中。
*/
public class Client implements Car{ //顾客可以直接找汽车商买车
@Override
public void buyCar() {
System.out.println("顾客自己找汽车商买车并付款");
}
}
public class ProxyCar implements Car {//汽车代理商(所谓的中介)
private Client client; //因为顾客需要自己付款 所以此处需要声明顾客对象
public ProxyCar(Client client) {
this.client = client;
}
@Override
public void buyCar() {
System.out.println("顾客找到中介告知要买一个车");
proProcess();
client.buyCar(); //顾客自己付款
postProcess();
}
public void proProcess(){
System.out.println("代理商询问顾客想要的车型价位等信息");
}
public void postProcess(){
System.out.println("代理商三包服务将汽车送到顾客手中");
}
}
public class Test {
public static void main(String[] args) {
Client client = new Client();
client.buyCar();//测试顾客自己找汽车商
ProxyCar proxyCar = new ProxyCar(client);
proxyCar.buyCar();//测试顾客找代理商购车
}
}
结果:
jdk自动的动态代理: java-lang.reflect.Proxy
//定义一个抽象主题
public interface Start {
void confer(); //面谈
void singContract(); //签合同
void bookTicket();//订票
void sing();//唱歌
void coolectMoney();//收钱
}
//具体主题
public class RealStatrt implements Start {
@Override
public void confer() {
System.out.println("本人面谈");
}
@Override
public void singContract() {
System.out.println("本人签合同");
}
@Override
public void bookTicket() {
System.out.println("本人订票");
}
@Override
public void sing() {
System.out.println("本人唱歌");
}
@Override
public void coolectMoney() {
System.out.println("本人收钱");
}
}
//定义一个动态代理处理器接口 必须实现InvocationHandler
public class StartHandler implements InvocationHandler {
Start realStart; //处理真实的角色
public StartHandler(Start realStart) { //通过构造器将角色传入
this.realStart = realStart;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用的所有方法都在此处处理 所以在此处可以进行统一功能处理
Object object = null;
System.out.println("唱歌方法执行前");
System.out.println("面谈签合同订票");
if (method.getName().equals("sing")) {
/*
如果是唱歌方法 就调用本人 其他方法可以在外部统一处理
因为代理无法完成唱歌
只有明星本人才可以唱歌
*/
method.invoke(realStart, args);
}
System.out.println("唱歌方法执行后");
System.out.println("收钱");
return object;
}
}
public class Client {
public static void main(String[] args) {
Start start = new RealStatrt();
StartHandler startHandler = new StartHandler(start);
//代理类代理对象
Start proxy = (Start) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader()
, new Class[]{Start.class}, startHandler);
proxy.sing();
}
}
结果:
动态代理和静态代理:
静态代理是一个主题类和一个代理类一一对应
动态代理是多个主题类可以和一个代理类对应 共享前后处理方法 只改变所需的主题即可。