码迷,mamicode.com
首页 > 其他好文 > 详细

【设计模式】代理模式详解

时间:2015-07-01 12:19:48      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:java   设计模式   代理模式   proxypattern   

前言

博主只是一名大三学生,文章内容难免有不足之处,欢迎批评指正。

 

正文

转载请注明出处: 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

技术分享

通过代理模式我们就能简洁地实现上传功能了,同时附加了其他功能。对以后的修改也变得很方便,只需在代理类中修改即可。


代理模式的优缺点

优点

代理类为被代理的对象增加了一些扩展,在真实目标类上加入一些其它操作,而这些操作的细节都交给代理处理,你只需要集中目标类功能的实现。同时便于以后的修改。

缺点

会有很多代理类,类变多了。


关于代理模式的动态代理,我想和反射放在一起。估计下个星期发出来(^_^)

版权声明:本文为博主原创文章,未经博主允许不得转载。

【设计模式】代理模式详解

标签:java   设计模式   代理模式   proxypattern   

原文地址:http://blog.csdn.net/h28496/article/details/46707621

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!