前言
博主只是一名大三学生,文章内容难免有不足之处,欢迎批评指正。
正文
转载请注明出处: http://blog.csdn.net/h28496/article/details/46707621
发 表 时 间: 2015年7月1日
什么是代理模式?
为其他对象提供一种代理,用来控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式常被分为远程代理、虚拟代理、保护代理等等。
代理模式的结构
UML类图
角色介绍
① 抽象接口:被代理类和代理类都需要实现的接口,定义了某个/些功能;
② 被代理类:定义了被代理的对象;
③ 代理类:代理对象内部含有一个被代理的对象,从而可以在内部操作目标对象。代理类实现了一个和被代理类相同的接口,以便可以在任何时候替代目标对象。
代理模式初步实现
假设场景:
老师给了女生50KG的东西,需要搬进宿舍楼,但是她们力量有限,一次只能搬25KG。
因此我们需要给女生设置一个代理,即男生。
老师把东西给男生,男生分次给女生25KG的东西搬,直到搬完。
(男生不能进女生寝室……不能直接帮她们搬。)
题目分析:
首先我们需要一个接口,该接口有一个方法carray(int weight),实现搬东西的功能。
然后我们要有一个女生类Girl,作为被代理类。
其次还要有一个男生类Boy,作为代理类。
最后还要有个客户端类。
ICarry.java
package zhp.proxypattern;
/**
* 搬运东西的接口,供 Boy 类 和 Girl 类实现。
* @author 郑海鹏
* @since 2015年6月18日
*/
public interface ICarry {
public void carry(int weight);
}
Girl.java
package zhp.proxypattern;
/**
* Girl类,被代理类。
* @author 郑海鹏
* @since 2015年6月18日
*/
public class Girl implements ICarry{
public final static int MAX_WEIGHT = 25;
@Override
public synchronized void carry(int weight) {
// 可以思考一下为什么有这个同步锁
if(weight > MAX_WEIGHT){
// 超过25KG,女生搬不动
System.out.println("我搬不动!!");
return;
}
System.out.println("我把" + weight + "公斤的东西搬完了。");
}
}
Boy.java
package zhp.proxypattern;
/**
* 代理类
* @author 郑海鹏
* @since 2015年6月18日
*/
public class Boy implements ICarry {
private Girl girl = new Girl(); // 拥有一个被代理的对象
private int mWeight = 0;
@Override
public void carry(int weight) {
mWeight += weight;
while(mWeight > 25){
girl.carry(25);
mWeight -= 25;
}
if(mWeight != 0){
girl.carry(mWeight);
}
}
}
Client.java
package zhp.proxypattern;
/**
* 客户端
* @author 郑海鹏
* @since 2015年6月18日
*/
public class Client {
public static void main(String[] args) {
Girl girl = new Girl();
pleaseCarry(girl, 50); // 让女生搬50KG的东西
System.out.println("---------------------");
Boy boy = new Boy();
pleaseCarry(boy, 50);
}
public static void pleaseCarry(ICarry carry, int weight){
carry.carry(weight);
}
}
执行结果:
在这个例子中,女生类不合适被用到于weight>25的场合中,从而使用代理类Boy进行缓冲,保护了被代理类。
代理模式在Android中的应用
代理模式在Android开发中经常被用到,例如:Android执行某个操作可能会很耗时,因此在主线程中应该避免此类耗时操作。可以使用一个代理类,实现耗时操作的接口,在主线程中交给这个代理类去做,当然代理类会开辟一个子线程。
假设场景:
我们已经有了一个实现IUpload接口的类UploadPic,可以用来上传图片。
但在Android中是不能直接在主线程中要上传图片到服务器的。
当然我们可以新建一个子线程去上传,但代码复用性太低了。如果以后需要修改某个参数,就得去修改每个上传用的子线程。
使用代理模式去处理这个问题就是个不错的选择。更好的是,我们可以在代理时,可以再执行一些其他操作,例如检查网络。
分析问题:
首先得有个接口:IUpload,接口定义上传操作。
还有个被代理类:UploadPic,实现IUpload接口,并提供上传图片的基本功能。
再有一个代理类:Proxy_UploadPic,同样实现IUpload接口,包含一个UploadPic的对象。
IUpload.java
package zhp.pattern.proxypattern;
/**
* 上传接口。
* @author 郑海鹏
* @since 2015年6月18日
*/
public interface IUpload {
/**
* 上传文件
* @param path 要上传的文件路径
*/
public void upload(String path);
}
UploadPic.java
package zhp.pattern.proxypattern;
/**
* 上传图片的类。
* @author 郑海鹏
* @since 2015年6月18日
*/
public class UploadPic implements IUpload {
@Override
public void upload(String path) {
// 输出:正在上传
zhp.android.debug.Debug.Log(this.getClass().getName(), "正在上传!");
}
}
Proxy_UploadPic.java
package zhp.pattern.proxypattern;
import android.content.Context;
import zhp.android.utils.Utils_Network;
/**
* 代理类,用于在子线程中上传图片
* @author 郑海鹏
* @since 2015年6月18日
*/
public class Proxy_UploadPic implements IUpload {
UploadPic uploadPic;
Context context;
public Proxy_UploadPic(Context context) {
this.context = context;
this.uploadPic = new UploadPic();
}
@Override
public void upload(final String path) {
// 先检测网络
boolean isWifiConned = Utils_Network.getInstance().isWifiConnected(this.context);
if(!isWifiConned){
// 没有wifi的话,输出:wifi没有连接,无法上传!
zhp.android.debug.Debug.Log(this.getClass().getName(), "Wifi没有连接,无法上传!");
return;
}
// 再上传
new Thread(new Runnable() {
public void run() {
uploadPic.upload(path);
}
}).start();
}
}
MainActivity.java
package zhp.pattern.proxypattern;
import android.app.Activity;
import android.os.Bundle;
/**
* 客户端
* @author 郑海鹏
* @since 2015年6月18日
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 使用代理上传,附加网络状态监测
uploadPicture(new Proxy_UploadPic(this), "sdcard/a.png");
}
private void uploadPicture(IUpload upload, String path){
upload.upload(path);
}
}
执行结果:
没有wifi
有wifi
通过代理模式我们就能简洁地实现上传功能了,同时附加了其他功能。对以后的修改也变得很方便,只需在代理类中修改即可。
代理模式的优缺点
优点
代理类为被代理的对象增加了一些扩展,在真实目标类上加入一些其它操作,而这些操作的细节都交给代理处理,你只需要集中目标类功能的实现。同时便于以后的修改。
缺点
会有很多代理类,类变多了。