`

你能用Wapper来做什么?

阅读更多

 从简单的说起:
一、在只有值传递的语言中,通过Wapper把实参Wapper之后,实现副作用:
在工具箱里写上我们要用的Wrapper:

public class Wrapper<T extends Object> {
	public T object;

	public Wrapper() {
		object = null;
	};

	public Wrapper(T object) {
		this.object = object;
	}
}

 下面我们看看一个从内部类获得副作用的例子:
由于内部类使用外部变量必须是final的,这样试图使用一个变量直接得到
内部类操作的结果不能够实现,这时候我们的Wrapper派上了用场:

final Wrapper<String> wrapper = new Wrapper<String>();
Display.getDefault().syncExec(new Runnable() {
	public void run() {
	   wrapper.object = ....;
	}
}

 我们可以成功的从一个内部类中获得我们需要的数据。


下面我们看一个经典的swap函数:

void swap(int a,int b){
   int temp = a;
   a = b;
   b = temp;
}

 这个简单的swap函数不起作用的,而java等语言参数传递只支持值传递,
所以不管是参数是基本类型还是Object类型,都不能写出可以swap两个值的函数。
如果我们非得想有这么一个swap函数来交换两个值,那该怎么办?这时候wapper又派上用场了。
在我们的工具箱找到Wrapper:
写我们的交换函数:

void swap(Object a,Object b){
   Object temp = a.value;
   a.value = b.value;
   b.value = temp;
}
String a = "abc";
String b = "bcd";
Wrapper<String> wrapperA = new Wrapper<String>(a);
Wrapper<String> wrapperB = new Wrapper<String>(b);
swap(wrapperA,wrapperB);

 在用javascript写XPCOM的时候,数组及其大小作为返回值(由于idl与实现语言无关,
需要返回数组的大小),两个返回值,javascript是不支持的,并且在javascript
只有值传递的语言,使用参数直接作为返回值是不能实现的,这时候Wapper就派上了
用场:

idl:
void getArray(out unsigned long count,[retval, array, size_is(count)] out string aArray);

 js实现:

 

getArray: function(aCount){
  aCount.value = this.aArray.length;
  return this.aArray;
};

 

使用方法:

var aCount = {};一个Wapper
var array = xx.getArray(aCount);
xxx.alert(aCount.length);

  二、控制实例产生的个数/生命周期:
最常见的一个Wrapper要算单例模式了:

public class Singleton{
	private static Singleton instance = new Singleton();
	private Singleton(){
	}

	public static Singleton getInstance(){
		return instance;
	}
}

 这个Wrapper或许有点特别,自己Wrapper自己,来控制实例产生的个数/生命周期。
上次写了一个获取Post数据的firefox插件,XPCOM nsPostDataManager最早使用:

var catman = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
		
		catman.addCategoryEntry("JavaScript global property",
					CLASS_NAME,
					CONTRACT_ID,
					true, 
					true);

 来注册。
这样可以在网页全局访问getPostData和clearRequests接口方法。但是结果去每次都为空,跟踪发现
每打开一个新的Tab页,nsPostDataManager就会有一个新的实例生成,从而使得收集post请求的实例,
和在页面要使用的实例不是一个。这时候Wrapper又可以出头露面了,再写一个Wrapper组件nsPostDataService::

getPostData: function(aCount){
	//在XPCOM中getService每次使用一个实例,而createInstance每次创建一个实例
	var nsPostDataManager = Cc["@ibm.com/nspostdatamanager;1"].getService(Ci.nsIPostDataManager);
	return nsPostDataManager.getPostData(aCount);
},
	
clearRequests: function(){
	var nsPostDataManager = Cc["@ibm.com/nspostdatamanager;1"].getService(Ci.nsIPostDataManager);
	return nsPostDataManager.clearRequests();
}

 这时候把nsPostDataService注册成网页全局访问的就可以了。

三、控制对象的访问:
Proxy模式其实也是一个Wrapper,通过Wrapper这个对象来控制对象的访问,并转发消息到实际对象。
四、为对象动态增加行为:
Proxy模式的动态代理可以实现AOP,为对象动态增加行为。Spring的AOP就是使用了Java动态代理。
装饰模式可以动态的Wrapper对象,来为对象增加行为:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

Extension Object模式则可以为Object动态添加新的行为而不改变已有的接口,然后Query到需要的接口,使用新行为。
Wrapper还有很多使用的场合,希望大家补充。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics