前言
博主只是一名大三学生,文章内容难免有不足之处,欢迎批评指正。
正文
转载请注明出处: 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
通过代理模式我们就能简洁地实现上传功能了,同时附加了其他功能。对以后的修改也变得很方便,只需在代理类中修改即可。
代理模式的优缺点
优点
代理类为被代理的对象增加了一些扩展,在真实目标类上加入一些其它操作,而这些操作的细节都交给代理处理,你只需要集中目标类功能的实现。同时便于以后的修改。
缺点
会有很多代理类,类变多了。
关于代理模式的动态代理,我想和反射放在一起。估计下个星期发出来(^_^)
版权声明:本文为博主原创文章,未经博主允许不得转载。