示例源码:https://gitee.com/SIESteven/designpattern.git
一、什么是代理模式
为了对具体实现类的控制和管理的一种代码设计模型。
如上图所示,这种设计模式通常由三方面组成:主题角色(多为接口),实现主题角色,代理角色。外部需要时,随时调用。
Subject:抽象接口。为RealSubject和Proxy提供接口。通过实现同一接口,Proxy在RealSubject出现的地方取代它。
RealSubject:具体的实现类
Proxy持有RealSubject的引用。在某些例子中,Proxy可以负责RealSubject的创建与销毁。客户与RealSubject的交互必须通过Proxy。
代理模式又分为静态代理和动态代理。Java中动态代理还包括jkd和cglib两种实现方式
二、为什么提出代理模式
为了屏蔽外界对具体实现类的访问及管理。
三、如何实现
1、jdk动态代理
场景:甲方向乙方提出了需求。为了不让甲方控制、管理乙方的猿类,公司设置了产品经理来与甲方和猿类打交道。产品负责接收需求、简单评估需求、对猿类管理和访问。
如图所示。代理模式更注重过程。首先将实现需求这件事划分为两部分:甲方和乙方。
甲方:有某种要求
乙方:提供对要求的实现。包括猿、产品、老板。
乙方分为三种角色:老板、猿、产品。
老板:员工们都得给我好好干活
package proxy.myjdkproxy;
/**
* 主题接口:老板
*/
public interface IBoss {
void dealDemands();
void dealDemands(String demands);
}
猿:
明确贯彻老板实现甲方要求的理念
负责甲方要求的具体实现(搭建架构、写静态页)
package proxy.myjdkproxy;
/**
* @auther: Steven
* @created: 2018/2/7 22:35
* Description:程序猿
*/
public class Coder implements IBoss {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name ="Steven";
Coder(){
System.out.println("我是猿:Steven ");
}
public void dealDemands() {
System.out.println(" analysis demands ");
System.out.println(" design ");
System.out.println(" coding ");
System.out.println(" test ");
System.out.println(" commit code ");
}
public void dealDemands(String demands) {
System.out.println(" analysis demands :"+demands);
System.out.println(" design ");
System.out.println(" coding ");
System.out.println(" test ");
System.out.println(" commit code ");
}
}
产品(话事人):
明确贯彻老板实现甲方要求的理念
了解乙方小兵的信息
对小兵进行调度和访问
package proxy.myjdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @auther: Steven
* @created: 2018/2/7 22:40
* Description:产品经理
*/
public class Product implements InvocationHandler {
// get coder
private Coder coder;
public boolean isHaveIdleCoder() {
return haveIdleCoder;
}
public void setHaveIdleCoder(boolean haveIdleCoder) {
this.haveIdleCoder = haveIdleCoder;
}
private boolean haveIdleCoder;
public Object getInstance() {
haveIdleCoder=true;
System.out.println("客户您好,我是产品经理,正在核查是否有员工能处理您的问题");
// 判断是否有空闲程序猿
if (!haveIdleCoder) {
System.out.println("现在没有人手,没法儿接需求。抱歉");
return null;
}
System.out.println("哎呦,竟然有人闲着!");
System.out.println("----内部沟通----交由某猿开始处理需求");
this.coder = new Coder();
Class cl = coder.getClass();
// 获取新建coder的代理权
Object proxy = Proxy.newProxyInstance(cl.getClassLoader(), cl.getInterfaces(), this);
return proxy;
}
public Object getInstance(Coder coder) {
this.coder = coder;
Class cl = coder.getClass();
return Proxy.newProxyInstance(cl.getClassLoader(), cl.getInterfaces(), this);
}
/**
* 实现需求
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---内部沟通----"+this.coder.getName()+"即将处理你的需求");
Object result = method.invoke(this.coder, args);
System.out.println("客户您好,您的需求已经完成了,请您验收");
return result;
}
}
最后需要说明的一点就是,在网上的某些例子中,把代理操作放到了甲方的代码中来进行代理操作,感觉那样做不太合适。因此采用了如上的方式。
四、总结
动态代理实际上是通过java反射技术对字节码进行重组,在功能代码执行之前、执行中、执行后可以进行操作。实践了AOP的思想。