代理模式:为其他对象提供一种代理以控制对这个对象的访问。
使用场景:当无法或者不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象间接的访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。
例:
现在我们想买一个美国版本的苹果手机,我们得游过太平洋才能到达美国买。很明显,我们对买手机这件事实现有点困难。我们需要一个代购公司帮我们买一下。在这个例子中:代购就是代理类,苹果厂商是被代理类。在此之前我们得建个父类规范厂商的活动。
国外厂商:
public interface OtherCountryCampty {
void saleTing();
}
苹果厂商:
public class AppleCampty implements OtherCountryCampty {
@Override
public void saleTing() {
System.out.println("iPhone 10 :6000rmb");
}
}
苹果代理商:
public class PhoneProxy implements OtherCountryCampty {
//其他国家的厂商
private OtherCountryCampty otherCountryCampty;
public PhoneProxy(OtherCountryCampty otherCountryCampty) {
this.otherCountryCampty = otherCountryCampty;
}
public OtherCountryCampty getOtherCountryCampty() {
return otherCountryCampty;
}
public void setOtherCountryCampty(OtherCountryCampty otherCountryCampty) {
this.otherCountryCampty = otherCountryCampty;
}
private void before() {
//先得和客户说明产品参数
System.out.println("产品参数介绍");
}
private void after() {
System.out.println("我们的售后保证");
}
@Override
public void saleTing() {
before();
otherCountryCampty.saleTing();
after();
}
}
如上,我们的苹果代理商,在给我们出售苹果手机前后,也有他们一定的服务。这就是我们的静态代理模式。
如果现在我们又想买一款美国的M416,来提高我们在吃鸡游戏中的吃鸡概率时。现在我们再找卖M416的代购,看起来没啥问题。但是,我们是不是可以用一个代理就实现这两种事情。不用,加一个需求,就多加一个代理类呢?这就是引出了动态代理模式。代码如下:
public class TotalProxy implements InvocationHandler {
//海外产品
private Object totalCampty;
public TotalProxy(Object totalCampty) {
this.totalCampty = totalCampty;
}
private void before() {
System.out.println("动态代理:售前合作");
}
private void after() {
System.out.println("动态代理:售后服务");
}
public Object getIntenes( Class<?>[] interfaces) {
return Proxy.newProxyInstance(totalCampty.getClass().getClassLoader(),interfaces, this);
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
before();
Object temp = method.invoke(totalCampty, objects);
after();
return temp;
}
}
客户端使用:
//静态代理模式
OtherCountryCampty phoneProxy=new AppleCampty();
PhoneProxy phoneProxy1=new PhoneProxy(phoneProxy);
phoneProxy1.saleTing();
//动态代理模式
OtherCountryCampty otherCountryCampty=new AppleCampty();
OtherCountryCampty phoneProxy2= (OtherCountryCampty) new TotalProxy(otherCountryCampty).getIntenes(new Class[]{OtherCountryCampty.class});
phoneProxy2.saleTing();
客户端使用,我们可以看出:动态代理模式,我们少了对应的代理类。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
接下来,我们看看JDK封装的代理机制:
InvocationHandler接口中的实现方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy---代理的对象
method---代理对象中需要代理的方法
args----方法中的参数
Proxy的newProxyInstance 方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader---这个类的类加载器(涉及到双委托机制,之后我们会讲)
interfaces---这是我们需要代理的接口的集合
h ---- 这个h明显就是上面我们讲到的那个InvocationHandler接口
------------------------------------------------------------------------------------------------------------------------------------------------------------------------