Java 设计模型--代理模式
2020-04-13 本文已影响0人
superHang
代理模式就是:当前对象不愿意干的,没法干的东西委托给别的对象来做,我只要做好本分的东西就好了!
https://www.cnblogs.com/doucheyard/p/5737366.html
静态代理
上面的文章挺好的,我就直接复用例子就好了
用小婴儿说明,小baby只会吃和睡,拉了粑粑,但是自己不会擦屁股呀,然后他妈妈只能找个保姆,保姆就是被他妈妈代理来照顾婴儿
public class Baby implements Human {
@Override
public void eat(){
System.out.println("小婴儿只能吃奶....");
}
@Override
public void shit() {
System.out.println("小婴儿拉粑粑....");
}
//保姆类---一个代理类
public class BabySitter implements Human {
private Baby baby;
//构造函数
public BabySitter(Baby baby){
this.baby=baby;
}
public void wipeShit(){
System.out.println("帮助婴儿擦屁屁。。。。");
}
@Override
public void eat() {
}
@Override
public void shit() {
baby.shit();
//帮助婴儿擦屁屁
wipeShit();
}
}
将婴儿和保姆关联起来,并在保姆类中添加帮助擦屁屁的方法
public class BabySitter implements Human {
private Baby baby;
//构造函数
public BabySitter(Baby baby){
this.baby=baby;
}
@Override
public void shit() {
//拉粑粑
baby.shit();
//擦屁屁
wipeShit();
}
public void wipeShit(){
System.out.println("帮助婴儿擦屁屁。。。。");
}
妈妈调用
public class Mom {
public static void main(String [] args){
Human human = new BabySitter(new Baby());
human.shit();
}
}

装饰模式主要是强调对类中代码的拓展,而代理模式则偏向于委托类的访问限制。两者都一样拥有抽象角色(接口)、真实角色(委托类)、代理类 。
动态代理
实现InvocationHandler
public class HealthHandle implements InvocationHandler {
private Object proxyTarget;
public Object getProxyInstance(Object target){
this.proxyTarget = target;
//Proxy.newProxyInstance(Clas loader, Class<?>[] interfaces, InvocationHandler h)
return Proxy.newProxyInstance(proxyTarget.getClass().getClassLoader(), proxyTarget.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object methodObject = null;
if(method.getName().equals("shit")){
methodObject = method.invoke(proxyTarget, args);
System.out.println("帮助婴儿擦屁屁.......");
}else if(method.getName().equals("eat")){
System.out.println("帮助婴儿饭前洗手.......");
methodObject = method.invoke(proxyTarget, args);
}
return methodObject;
}
妈妈类调用,动态代理了两个动作,在婴儿拉粑粑后,帮他洗屁屁,在他吃饭前,帮他洗手,不再用保姆类了
public static void main(String [] args){
HealthHandle h = new HealthHandle();
Human human = (Human) h.getProxyInstance(new Baby());
human.shit();
human.eat();
}

使用动态代理:
1.必须实现InvocationHandler接口,订立一个契约标识该类为一个动态代理执行类
2.InvocationHandler接口内有一实现方法签名如下: public Object invoke(Object proxy, Method method, Object[] args) 。使用时需要重写这个方法
3.获取代理类,需要使用 Proxy.newProxyInstance(Clas loader, Class<?>[] interfaces, InvocationHandler h) 这个方法去获取Proxy对象(Proxy类类型的实例,非BABY类类型实例)。
就是不能写成 :
Baby baby = (Baby) h.getProxyInstance(new Baby());
要写他的抽象类
//Clas loader : 类的加载器
//Class<?>[] interfaces : 委托类实现的接口,保证代理类返回的是同一个实现接口下的类型,保持代理类与抽象角色行为的一致
//invocationHandler, 该类最重要的一环。一个设计模式:策略模式.即告诉代理类,代理类遇到某个委托类的方法时该调用哪个类下的invoke方法。
Proxy.newProxyInstance(Class loader, Class<?>[] interfaces, InvocationHandler h)
//第一个参数为Proxy类类型实例,如匿名的$proxy实例
//第二个参数为委托类的方法对象
//第三个参数为委托类的方法参数
//返回类型为委托类某个方法的执行结果
public Object invoke(Object proxy, Method method, Object[] args)
总的来说这个方法就是动态获取委托类里面的方法,在调用委托类的方法时在这个方法内进行拓展。 通过上面的Proxy.newProxyInstance方法,告诉底层代码,该去哪个类里面执行invoke方法。
``