1.代理模式
代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。
更言简意赅就是如下图:
老张最近比较困惑,于是想买个情趣用品解解压,但是老张又是一个比较爱面子的人,想用好的产品,那么日本进口产品就成了他的第一选择,假设没有代理的情况下,老张就需要自己去日本购买,又费时费力,如果有了代理,那么他就只用给代理说我要买哪个款式的xx娃娃,其他的就不用他管了,全交给代理去弄就行了,那么代理就可以根据他的要求进行市场调研,然后在帮他选择合适的产品,然后打包好邮寄给老张,那么老张就可以坐在家里等着收货,然后激情四射即可。(代理能减少复杂性,同时还能对原有业务进行增强)。
2.静态代理
代理模式又分为静态代理和动态代理,两者的有很大的区别,先讲静态代理,还是和上面一样的场景,首先我们要清楚代理的三要素:抽象对象(接口,也就是男性情趣用品公司),真实对象(接口的实现,也就是具体的男性情趣用品公司),代理(proxy,代理人)
我们来看代码:
首先定义一个商店接口
//商店接口
package com.daili.test;
public interface store {
void Sellsometing(String name);
}
在定义一个实体店(真实对象)
//实体店
package com.daili.test;
public class aastore implements store {
@Override
public void Sellsometing(String name) {
System.out.println("购买"+name+"款娃娃一个,祝大爷玩的开心");
}
}
在定义一个代理(微商)
package com.daili.test;
//微商代理
public class xxproxy implements store {
//包含提供服务对象
public store teststore;
public xxproxy(store teststore){
super();
this.teststore=teststore;
}
@Override
public void Sellsometing(String name) {
dosomethingbefore();//前置增强
teststore.Sellsometing(name);
dosomethingafter();//后置增强
}
public static void dosomethingbefore(){
System.out.println("进行市场调研");
}
public static void dosomethingafter(){
System.out.println("进行私密打包");
}
}
然后顾客老张直接找代理下单。
package com.daili.test;
import com.daili.test.xxproxy;
import com.daili.test.aastore;
//客户老张
public class zhangshan {
public static void main(String[] args) {
aastore Aastore = new aastore();
xxproxy XXproxy = new xxproxy(Aastore);
XXproxy.Sellsometing("波多野结衣");
}
}
最后输出的结果。
总结:
1.无需修改被代理的对象
2.无损拓展功能
3.解耦合
缺点当然也存在:
要为每一个接口实现代理类,一旦接口增加方法,目标对象与代理对象都要维护。
3.动态代理。
显然静态代理,需要我们实现每一个接口,而且随着接口的增加,代理的可维护性就逐渐降低,比如这时候老王又比较喜欢球鞋,但是奈何国内买不到真货,且都比较贵,所以也想找微商代理购买,在出现这个需求后,因为原本微商只做一个业务,那就是购买情趣用品,现在有钱赚不可能不赚啊,那么微商又的去重新找商店,重写代理类等等,就很麻烦,那么动态代理就能解决这个问题。
如上图所示,我们可以把动态代理比喻成一个代购公司,公司里集结了各行各业的代理,只有顾客想不到,没有公司买不到。
看代码。
还是一样,先定义一个接口
//商店接口
package com.daili.test;
public interface store {
void Sellsometing(String name);
}
定义两个实体店:
package com.daili.test;
public class bbstore implements store {
@Override
public void Sellsometing(String name) {
System.out.println("卖出一双"+name+"鞋子,老板发财");
}
}
package com.daili.test;
public class aastore implements store {
@Override
public void Sellsometing(String name) {
System.out.println("购买"+name+"款娃娃一个,祝大爷玩的开心");
}
}
创建一个代理公司:
package com.daili.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class yangyangjiecompany implements InvocationHandler {
//被代理对象(也就是哪家实体店)
public Object xxstore;
public Object getXxstore() {
return xxstore;
}
public void setXxstore(Object xxstore) {
this.xxstore = xxstore;
}
//
public Object getproxyinterface(){
return Proxy.newProxyInstance(xxstore.getClass().getClassLoader(),xxstore.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
dosomethingbefore();
Object ret = method.invoke(xxstore,args);
dosomethingafter();
return ret;
}
public static void dosomethingbefore(){
System.out.println("进行市场调研");
}
public static void dosomethingafter(){
System.out.println("进行私密打包");
}
}
最后老张想买一双鞋子,还有一个xx就可以这么写。
package com.daili.test;
import com.daili.test.store;
import com.daili.test.aastore;
import com.daili.test.bbstore;
//客户老张
public class zhangshan {
public static void main(String[] args) {
store Aastore = new aastore();
yangyangjiecompany YYJ = new yangyangjiecompany();
YYJ.setXxstore(Aastore);
store xx1 = (store) YYJ.getproxyinterface();
xx1.Sellsometing("吉泽明步");
System.out.println("==========================");
store Bbstore = new bbstore();
YYJ.setXxstore(Bbstore);
store xx2 = (store) YYJ.getproxyinterface();
xx2.Sellsometing("阿迪");
}
}
可以看到我并没有像静态代理那样重新实现一个代理类,而是实现了 InvocationHandler 接口的invoke方法实现的代理。通过Proxy.newProxyInstance()创建了一个代理类来执行sell方法。
静态代理与动态代理的区别主要在:
静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中
java.lang.reflect Proxy,主要方法为
static Object newProxyInstance(ClassLoader loader, //指定当前目标对象使用类加载器
Class<?>[] interfaces, //目标对象实现的接口的类型
InvocationHandler h //事件处理器
)
//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
java.lang.reflect InvocationHandler,主要方法为
Object invoke(Object proxy, Method method, Object[] args)
// 在代理实例上处理方法调用并返回结果
总结完毕,如果有错误,请师傅们斧正。