您的位置:首页 > 编程语言 > Java开发

java代理模式-静态代理学习

2016-11-01 00:33 211 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。

尊重原创:http://blog.csdn.net/bingju328/article/details/52989307

前言: 最近在看一款基于异步线程的网络请求框架Retrofit,随着okhttp的广泛应用和RxJava的兴起,刚好Retrofit自身也支持okhttp和RxJava,所以Retrofit逐渐的为大家所熟知,成为大多数开发者的首选。做为一名爱(bei)学(po)习(xue)的程序狗,本者不断进取,渴望新知的精神,研究了一下Retrofit,而里面所用到的主要的设计模式就是基于java代理模式的动态代理,本篇文章是我对java代理模式学习的记录,从代理模式的定义、实现、应用及好处等方面进理解。

定义:《JAVA与模式》中是这样描述的:代理模式是对象的结构模式。它给某个对象提供一个代理对象,并由代理对象控制对原对象的引用。其实就是字面上的意思,比如我们租房子的时候,我们发出租房子的需求给代理商(代理类)(即:中介),然后中介和房子(目标对象)的主人发出需求,从而达成了租房子的这个操作。

UML类图结构如下:



在代理模式中的角色:

抽象对象角色(RentSubject):声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。

目标对象角色(FTXRentSubject):定义了代理对象所代表的目标对象。

代理对象角色(ProxyFTXSubject):代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象。

源代码如下:

定义抽象角色

/**
* 抽象主题,定义主要功能的接口
* 功能:rent() 租房
* */
public interface RentSubject {

public String rent(String operation);

}


定义具体主题(目标对象角色)

/**
* (房天下公司房子的房主)具体主题,是对抽象主题的实现
* */
public class FTXRentSubject implements RentSubject {
public String rent(String operation) {
//房主具体的操作
System.out.println("FTXRentSubject--"+operation);
return operation;
}
}


定义代理对象角色

/**
* (房天下公司)代理对象角色,替目标对象(即具体主题,{@link FTXRentSubject})来做相关的操作
* */
public class ProxyFTXSubject implements RentSubject {
private FTXRentSubject ftxRentSubject;

public ProxyFTXSubject(FTXRentSubject ftxRentSubject) {
this.ftxRentSubject = ftxRentSubject;
}

public String rent(String operation) {
//房东租房前的操作
System.out.println(operation+"-before");
//调用目标对象的方法来操作
//此调用方式实质上也是类ProxyFTXSubject和FTXRentSubject之间的一种"组合方式" 的调用
//主要作用是:在需求变更的时候操作代理对象ProxyFTXSubject而不用改变FTXRentSubject类
//从而达到了解耦的效果
ftxRentSubject.rent(operation);
//房东租房后的操作
System.out.println(operation+"-after");
return operation;
}

}


客户端类

/**
1. (房天下公司)代理对象角色,替目标对象(即具体主题,{@link FTXRentSubject})来做相关的操作
2. */
public class Client {
public static void main(String[] args){
//房天下的房东客户不能直接找房东租
FTXRentSubject ftxRentSubject = new FTXRentSubject();
ProxyFTXSubject proxyFTXSubject = new ProxyFTXSubject(ftxRentSubject);
//客户给房天下公司发出需求:租房子
proxyFTXSubject.rent("房天下客户租房子");
}
}


好处:

在某些情况下,客户端不能或者不便直接操作标对象时,可以通过代理对象来操作。

代理模式能降低客户端对象和目标对象的耦合性。

可以实现无侵入的代码扩展。

以上几点算是比较好理解的好处了。那这个时候有人问了,光说好处好像都知道,百度、google上一大堆,能不能具体点?能必须能,其实代理模式之前也看过好多次了,但也只是大概知道一点,以便来应付面试,但我们终究是选择了程序员这条路,如果你本身对这一行非常有兴趣那最好不过了,如果只是为了生活,也可以自己培养兴趣,正所谓干一行爱一行嘛。

应用:

对于第一条,在某些情况下,就比如我上面举的不算太恰当的例子,大多房东不想花费时间自已租房子所以把房子托管给中介,这样就导致客户只能和中介交互,也就是客户类和代理类交互从而达到租实体对象(房东)的房子的目的。

对于第二条,因为客户没有直接操作实体对象,就是说客户类和实体类没有太多的关联,如果通过客户类直接调用实体类,那么客户类就和实体类产生了直接的联系(即耦合度增大了,不利于代码的扩展和复用)

对于第三条,无侵入是指当需求改变的时候,我们完全不用改动实体对象类的代码就可以满足新的需求,比如说:上面的例子是,客户租房子只交钱就好了,而从上个月开始,租小区房子需要有居住证才让租,那这个新需求怎么在不改实体对象的情况下实现呢。

首先我们新建个 办理居住证明的操作类:HandleJuZhuPermit如下:

/**
* 办理居住证明的操作类
* */
public class HandleJuZhuPermit {
private String operation;

public HandleJuZhuPermit(String operation) {
this.operation = operation;
}
public String handlePermit(String addoperation){
return addoperation +"--"+ operation;
}
}


在Client中这么使用

/**
* 客户
* */
public class Client {
public static void main(String[] args){
//房天下的房东客户不能直接找房东租
FTXRentSubject ftxRentSubject = new FTXRentSubject();
ProxyFTXSubject proxyFTXSubject = new ProxyFTXSubject(ftxRentSubject);
//客户给房天下公司发出需求:租房子
proxyFTXSubject.rent("房天下客户租房子");

//从现在开始所有所有客户都要办理居住证才可以租房子
proxyFTXSubject.rent(new HandleJuZhuPermit("房天下客户租房子").handlePermit("先办理居住证"));
}
}


当然这个时候又有人问了,不是可以在实体类里面直接改不就好了,这样也是可以的,但是如果这么做的话,这个实体类就只能是这个客户类用了,这个程序的其它地方就不能用了,而且如果有多个实体类,比如说 房东的实体类不只有房天下的,还有链家、爱屋吉屋的咋么办,你还要一一都改了么。如果一一都改了,那也得把用到这些实体类的所有的类都检查一遍,光想想整个人都不好了~_~!!!。

对于上面的例子,有一个问题我们可以思考一下 : 代理类能别用那么多么?是否可以用一个代理角色来代替所有的代理角色呢? 那么下一篇将会记录一下动态代理相关的知识。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息