设计模式之代理模式
来源:互联网 发布:管理者心态管理知乎 编辑:程序博客网 时间:2024/06/12 00:12
代理模式在我们生活中是十分常见的,例如,帮我打包午饭,帮我拿一下快递,这些是我们日常的代理模式。其中你是委托人,代理人是你朋友,而事件就是打包午饭、拿快递。
简介
代理模式的定义:Provide a surrogate or placeholder for another object to controlaccess to it(为其他对象提供一种代理以控制对这个对象的访问)。
模式中的角色与职责
Subject: 抽象主题类
该类的主要职责是申明真是主题与代理的共同接口方法,该类既可以是个抽象类也可以是个接口(具有抽象方法)。
RealSubject: 真实主题类
该类也称为委托类或者被代理类,该类定义了代理所表示的真是对象(也就是实现了抽象方法),由其执行具体的业务逻辑。
ProxySubject:代理类
这个类的对象持有一个对真实主题的引用,在这个类所实现的接口方法中调用真实主题类中相应的方法执行,这样就实现了代理的目的。
Client:客户类
也就是使用代理类的类型,客户类通过代理类间接地调用了真实主题类中定义的方法。
代理模式可以分为静态代理和动态代理。
静态代理
具体实现代码如下:
public class JavaDemo { public static void main(String[] args) { ProxySubject proxySubject = new ProxySubject(new RealSubject()); proxySubject.request(); }}interface Subject { abstract void request();}class RealSubject implements Subject { @Override public void request() { // TODO Auto-generated method stub System.out.println("To do something."); }}class ProxySubject implements Subject { private RealSubject mRealSubject; public ProxySubject(RealSubject realSubject) { super(); // TODO Auto-generated constructor stub mRealSubject = realSubject; } @Override public void request() { // TODO Auto-generated method stub mRealSubject.request(); }}
通过示例代码相信大家对静态代理有了一定的理解。
1.委托人和代理人都可以完成同样一件事。(实现同一个接口)
2.委托人告诉代理人去完成这件事,代理人才去做这件事。(代理人需要持有委托人引用)
动态代理
同样是带午饭的场景,但是自己写代码写到忘记了时间,一抬头发现同事都走光了,那么谁能帮自己带个饭呢?在等待的过程中是谁先出现,张三还是李四?(程序需要动态创建一个对象)而且最重要的是出现的那个同事要能帮自己带饭才行(上步创建的对象需要实现Subject接口)
public class JavaDemo { public static void main(String[] args) { final Subject realSubject = new RealSubject(); //第一个参数,目标的装载器 //第二个参数,目标接口,为每个接口生成代理 //第三个参数,实现了InvocationHandler接口,当你一调用代理,代理就会调用InvocationHandler的invoke方法 Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub //调用目标方法 return method.invoke(realSubject, args); } }); subject.request(); }}interface Subject { abstract void request();}class RealSubject implements Subject { @Override public void request() { // TODO Auto-generated method stub System.out.println("To do something."); }}
InvocationHandler相当于一个处理器,在invoke方法中我们能够操作真实对象,可以附加其他操作。而我们通过Proxy.newProxyInstance(..)方法生成代理。实现InvocationHandler接口并附加操作后,获取代理角色。
动态代理的重点在于Proxy.newProxyInstance(),有兴趣的同学可以看看里面的实现源码。主要步骤是:
1.ProxyGenerator.generateProxyClass方法负责生成代理类的字节码,生成逻辑比较复杂,有兴趣的同学可以继续分析源码 sun.misc.ProxyGenerator;
2.native方法Proxy.defineClass0负责字节码加载的实现,并返回对应的Class对象。
3.利用clazz.newInstance反射机制生成代理类的对象;
而动态代理是相当强大的,下面我们自己看一下Retrofit的动态代理例子:
Retrofit是现在最火的Android网络请求框架之一,相信大家或多或少都有了解过。我们看一下Retrofit怎么使用动态代理模式的。
1.创建一个请求方法的接口:
public interface HttpService { @FormUrlEncoded @POST(URLs.Login) Call<JSONObject> login(@FieldMap() Map<String, String> maps);}
2.生成Retrofit对象,并且创建一个实现了GitHubServiece接口的实体类:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .build();HttpService mHttpService = retrofit.create(HttpService.class);
上面的大家用过Retrofit都会很熟悉,我们看一下create()的代码:
public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(service); } return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, Object... args) throws Throwable { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod serviceMethod = loadServiceMethod(method); OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
经过上面对动态代理的理解,对create()封装的代码,一看就非常清楚,就是动态代理模式嘛。
了解了静态代理和动态代理可能大家会想,在代码层面上本来就可以自己完成,为什么要交给其他类完成呢?这样不是多此一举吗?但在实际开发中,使用代理模式的作用有:
解耦:这是设计模式解决的基本问题。在这里委托类只需要做好自己的部分工作,然而一些额外的事情可以交给代理类完成。如自己准备结婚,但是不可能自己去一手一脚去准备整个婚礼,我们自己只需要请婚庆公司,定好价钱然后婚庆公司就能帮我们解决整场婚礼的大小事,我们自己不需要婚庆公司怎么完成,这样是不是将我与结婚事件进行了解耦。
拦截、扩展:代理类在实现接口方法的时候,除了调用委托类方法外,还可以在不修改委托类的情况下,增加一些其他需求功能。如我们试想在实现类满足要求时,我们可以直接使用实现类,但是实现类再满足不了需求的时候,我们就得扩展,但是根据开闭原则,我们不能直接修改实现类的代码,这样我们可以通过代理类可扩展功能;另外就是我们权限分配,我们可以根据对申请权限的对象进行拦截,根据不同的角色条件做判断,然后再分配对用的权限。
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之-代理模式
- 设计模式之 代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- 设计模式之-----代理模式
- 设计模式之代理模式
- 设计模式之-代理模式
- 设计模式之代理模式
- 设计模式之代理模式
- spark on yarn部署
- GCC选项 –I,-l,-L
- C++11新特性
- [目标检测]windows下实现c++版faster-rcnn
- C# base 关键字
- 设计模式之代理模式
- linux的部分基础操作
- 梦幻西游手游桌面版启动不了,报错
- vc应用程序描述
- sqlserver实现树形结构递归查询(无限极分类)
- Angular JS 笔记
- wireshark基本用法及过虑规则
- LeetCode: Partition Equal Subset Sum
- zookeeper 原理和使用