2.对象数量-单件(singleton)+对象池(Object pool)
我们不是按模式的顺序进行介绍的,是按照需要解决的问题,来进行归类的
很多时候,我们需要控制对象的数量,为什么呢,因为不停的创建对象是一件耗资源的事情,而且会导致程序的思路没有那么的清晰,我们的宗旨是实际需要多少才给多少,如果只需要共享一个对象的资源,那么就使用单例吧,在我之前的一个面试中,我还记得那条友问我单例的作用是什么,我当时不懂如何应答,他说是为共享同一个资源,这个问题其实我还是想表达的是很多时候许多设计模式如果只是靠思考是很难能感受到他的好处的,必须用到项目中去,才能明白他的好处与用法,单例对我来说,当我用到项目中去时,我才会发现的确是用到了共享这一个对象的资源,当时我用的GPS的获取。
单件(singleton):
这个模式的别名超多,不过英文名只有一个就是singleton,他的一个很重要的作用是提供一个全局存取点,因为严格来说java是没有全局变量的(类似c那种的没有),使用singleton的一个重要用法是实现c中全局变量的代替方法,不过在真实应用中,经常我会把singleton中的内容作为共享资源,也就是全局变量这类,然后使用,效果还是不错的。不过我相信会有许多更有趣的用法。
示例
final class Singleton{
private static Singleton sg=new Singleton();
private Singleton(){}
public static getSingleton(){
return sg;
}
}
其实单件模式还是很好理解的,final是为了防止clone而来创建对象,因为sg是static所以只初始化一遍,而且构造方法是私有的,所以用户只能调用getSingleton()这个方法获取单例对象。
对象池(Object pool):
意图(Intent)
对象池可以显著提高性能。在某些场合,比如初始化一个类所需的代价很高时,实例化一个类很耗时 时,任一时间使用中的对象数目不多时,使用对象池是最为高效的。
难题(Problem)
对象池(也叫资源池)是用来管理对象缓存的。一个访问对象池的客户(client)可以避免创建一个新 对象,而只需向池中拿出一个已经实例化的对象。通常池都是"发展(growing)"的:当池是空的时候, 池会自动创建一些新的对象。我们也可以创建一个对象创建数量受到限制的池。
值得做的是,把所有可重用(Reusable)的当前未在使用中的对象放在同一个对象池中,以便以统一的 策略(policy)管理它们。代表这个可重用池的类(Reusable Pool class)应该被设计成单例的。
对象池允许其它类查看池中的对象,如果进程不再需要这些对象,它们就会被返回到池中以备复用。
但是,我们并不想让某个进程为了获得一个特定的对象而等待,所以如果需要,对象池也会(提前)实 例化一些新对象。但是必须实现一个方法,这个方法用来周期性的处理那些未被使用的对象(把它们放 入池中)。
结构(Structure)
连接池(对象池的一种)的大概猜想是,如果一个类的实例可以被复用,那你就复用它以避免再创建实 例。
并没有限制说只能创建一个对象。这种技术同样适用于创建固定数量的对象,但是,这种情况下,你就得面对如何共享对象池里的对象这种问题。如果共享对象很成问题得话,你可以考虑以签入(check-in)签出(check-out)共享对象作为一种解决方案。比如,就数据库来说,商业数据库通常会限制某一时刻可以使用的连接的个数。
示例
//对象池
class poolmanger{
/**这里使用单例来创建这个池
private static poolmanger pm=new poolmanger();
private poolmanger(){}
public static getPoolmanger(){
return pm;
}
//内部类对象
private static class poolitem{
boolean inUse=false;
Object item;
poolitem(Object item){
this.item=item
}
}
private ArrayList items = new ArrayList();
//创建池中的对象
public void add(Object item) { items.add(new PoolItem(item)); }
static class EmptyPoolException extends Exception {} //当池为空的时候抛出异常
//获取一个池中没有使用的对象
public poolitem get() throws EmptyPoolException {
for(int i=0;i<items.size();i++){
poolitem item=items.get(i);
if(item.inUse==false){
item.inUse=true;
return item;
}
}
// 当池为空时:
throw new EmptyPoolException();
//return null; // Delayed failure
}
//是否使用的对象,也就是将使用的对象返回池中
public void release(Object item){
for(int i = 0; i < items.size(); i++) {
PoolItem pitem = (PoolItem)items.get(i);
if(item == pitem.item) {
pitem.inUse = false;
return;
}
}
throw new RuntimeException(item + " not found");
}
} ///:~
}
以上就完成了一个对象池的创建了,具体使用也就先add,往里面放对象,其实以上例子这个东西的原理是这样的,定义一个list,然后一开始往里面放对象,都是静态的这些对象,所以下次使用不需要再次初始化,然后每个对象有一个标示inUse,表示是否正在使用,当用户要用对象,就向对象池申请,对象池就开始找,看看谁是没有被正在使用的,然后就返回给用户,当用户用完之后,就调用relase。实际上就是将标示定为false,标示该对像已经用完,现在没有人使用。这个对象池可以放的东西很多,而且很有用,这是一个模式,我觉得线程池也是这么一个模式构建出了的。这个模式的实用性觉得还挺高的。
other:
限制对象创建数量还有一个简单的方法,
class Soup1{
private Soup(){}
private static int i;
public static Soup1 makeSoup(){
if(i<10){ //这里就使对象创建次数控制在10次以内
return new Soup1();
i++;
}
}
}
欢迎讨论...