今天我和大家谈谈什么Java设计模式中代理模式,我相信大家也看过很多人写的代理模式讲解,在百度搜索Java 代理模式 一大推博客为我们讲解,我自己也看了很多这类博客文章,每次感觉都懂了,但是在项目开发中感觉自己还是不能灵活的运用,又要重新找资料理解,所以今天特地写这篇博客来记录下方便以后寻找,也为了加深印象吧!好了, 好了说完废话开始今天主题
代理模式
代理模式是什么?说到代理模式其中两个重要的类不的不提了,一个叫委托类,有人也叫什么主题类,还有人叫什么被代理的类等等,这个就看你喜欢叫什么了。至于另一个就叫代理类。我们知道在某些情况下,我们不希望或是不能直接去访问委托类对象 A,而是通过访问一个代理类对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理。大白话就是通过B去访问A,也可以在访问之前做些事情。
静态代理
上面知道了什么是代理模式,现在就讲讲代理模式两种方式吧!先讲讲静态代理 ,静态代理就是代理类在程序运行前已经存在的代理方式称为静态代理。意思就是开发人员编写或是编译器生成代理类的方式都属于静态代理。还是看代码吧!
委托类
/**
* 我是委托类
*/
public class RealA {
public void method1(){
System.out.println("我是委托对象的method1()方法!");
}
}
代理类
/**
* 我是代理类
*/
public class ProxyB {
private RealA a;
public ProxyB(RealA a) {
this.a=a;
}
public void method1(){
System.out.println("我是代理对象method1方法 我可以干点事帮a对象哦");
a.method1();
}
}
客户端
/*
*
* 我是客户端
*/
public class Client {
public static void main(String[] args) {
RealA real=new RealA();
ProxyB proxy=new ProxyB(real);
//调用 proxy的mthod1方法,即完成了 real的method1, 也帮它干了其他事,同时也不需要去改变RealA类 ,如果RealA原来存在的话
proxy.method1();
}
}
上面代码我相信大家可以清楚的了解什么是静态代理了 当然 有些博客会让委托类和代理类继承同一个接口,再来演示,其实我个人认为这样做的好处就是说可以定制规范,方便我们敲代码了。静态代理就讲完了 当然还有动态代理还没讲 ,等我好好看看之后再讲吧! 等我把动态代理讲完后 再来总结代理模式好处吧!未完待续O(∩_∩)O哈哈哈~
动态代理
今天就来讲讲动态代理,动态代理相对于静态代理要难点,但是没办关系每次遇到难点东西就是我们提高能力的时候到了。先说说动态代理含义吧!用比较官方的解释就是代理类在程序运行前不存在、运行时由程序动态生成的代理方式称为动态代理,用大白话说就是代理类由程序自动帮我们生产。
实现动态代理实例主要分三步
第一步:新建委托类。
第二步:. 实现InvocationHandler接口,这是负责连接代理类和委托类的中间类必须实现的接口。
第三步:通过Proxy类新建代理类对象
记住这三步 现在我们用代码说明
委托类
/**
* 委托类接口
* @author Administrator
*
*/
public interface Operate {
public void operateMethod1();
public void operateMethod2();
public void operateMethod3();
}
/**
* 委托类具体实现
* @author Administrator
*
*/
public class OperateImp implements Operate{
public void operateMethod1() {
System.out.println("Invoke operateMethod1");
}
public void operateMethod2() {
System.out.println("Invoke operateMethod2");
// TODO Auto-generated method stub
}
public void operateMethod3() {
System.out.println("Invoke operateMethod3");
}
}
第二步:实现InvocationHandler接口
public class TimingInvocation implements InvocationHandler {
private Object target;
public TimingInvocation(Object target){
this.target=target;
}
//每次调用委托类的方法时这个方法都会被调用
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object object = method.invoke(target, args);
System.out.println("方法名字:"+method.getName());
return object;
}
}
第三步:通过Proxy类新建代理类对象
public static void main(String[] args) {
TimingInvocation timingInvocation=new TimingInvocation(new OperateImp());
/*在这行代码中完成代理类生成,生成主要是调用ProxyGenerator.generateProxyClass( proxyName, interfaces);方法生成
* 第一个参数:类加载器
* 第二个参数:委托类的接口,生成代理类时需要实现这些接口 数据类型是 可变参数
* 第三个参数:InvocationHandler实现类对象,负责连接代理类和委托类的中间类
*/
Operate operate=(Operate) Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[]{Operate.class}, timingInvocation);
operate.operateMethod1();
operate.operateMethod2();
operate.operateMethod3();
}
到此为止动态代理怎么用已经完成,讲完使用应该讲讲原理是怎么的 ,但是我觉得动态代理原理比较复杂,所以我想新开一篇博客来写它,所以在这里我就不多讲了。那现在讲什么了呢?就讲讲他的使用场景吧!
动态代理使用场景
场景一:J2EE Web 开发中 Spring 的 AOP(面向切面编程) 特性
作用:目标函数之间解耦。
比如在 Dao 中,每次数据库操作都需要开启事务,而且在操作的时候需要关注权限。一般写法是在 Dao 的每个函数中添加相应逻辑,造成代码冗余,耦合度高。
使用动态代理前伪代码如下:
Dao {
insert() {
判断是否有保存的权限;
开启事务;
插入;
提交事务;
}
delete() {
判断是否有删除的权限;
开启事务;
删除;
提交事务;
}
}
是不是发现delete()和insert()方法有相同操作呀!这个时候我们就可以想到用动态代理请看 伪代码
// 使用动态代理,组合每个切面的函数,而每个切面只需要关注自己的逻辑就行,达到减少代码,松耦合的效果
//这个方法就是InvocationHandler接口中的invoke方法
invoke(Object proxy, Method method, Object[] args)
throws Throwable {
判断是否有权限;
开启事务;
Object ob = method.invoke(dao, args);
提交事务;
return ob;
}
是不是发现挺简单的,其实我认为很多东西你只要认真去学就会发现很简单也很有趣,我以前一直对动态代理不太懂今天通过这篇博客让我自己比以前理解的更加深刻,
场景二:基于 REST 的 Android 端网络请求框架 Retrofit
作用:简化网络请求操作。
一般情况下每个网络请求我们都需要调用一次HttpURLConnection或者HttpClient进行请求,或者像 Volley 一样丢进等待队列中,Retrofit 极大程度简化了这些操作,示例代码如下:
public interface GitHubService {
@GET("/users/{user}/repos")
List<Repo> listRepos(@Path("user") String user);
}
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.build();
GitHubService service = restAdapter.create(GitHubService.class);
以后我们只需要直接调用
List repos = service.listRepos(“octocat”);
即可开始网络请求,Retrofit的原理就是基于动态代理。