浅析单例模式
单例模式(singleton pattern),简而言之就是说一个类只能生成一个实例,而这个实例将被多个对象依赖。
那么,我们平常开发的时候,都是习惯了使用new关键字创建对象,应该怎么做才能够让一个类只生成一个对象呢?大家知道,在生成一个对象的时候,我们一般都是通过类的构造方法来生成对象的,那么当这个类的构造方法被设置成private的时候,要生成这个对象,就只能通过它内部来生成了。要做到一个类只生成一个对象,正是利用了这一点。我们来看代码:
public class Singleton {
private static Singleton singleton=null;
//私有的构造方法
private Singleton(){
}
//外部调用来获取实例
public static Singleton getSingleton(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
}
从上面代码可以看出,如果要产生一个单例,只需要返回这个构造方法为私有的并且在内部已经实例化的对象即可。但是,这种写法有一定的缺陷,它可能会产生线程不安全问题。举个例子,加入一个线程A执行到了singleton=new Singleton();,但是还没生成实例,而此时另外一个线程B执行到了singleton==null,条件为真,结果就产生了两个不同的对象,不过解决方法还是有的,比如可以加一个synchronized来锁住getSingleton方法,不过这种方法一般不被推荐。下面介绍一个比较安全的写法:
public class Singleton {
private static Singleton singleton=new Singleton();
//私有的构造方法
private Singleton(){
}
//外部调用来获取实例
public static Singleton getSingleton(){
return singleton;
}
}
这种单例又称为饿汉式单例,前者被称为懒汉式单例,这是一种比较推荐的写法,建议读者使用这种写法。
可能有人就会问,如果我想一个类生成固定数量的单例,应该怎么实现?哈哈,在这里告诉大家,这种想法确实可以实现,实现的方法呢也不难,只要在原来的基础上新增一个类属性——最多能产生的实例数量,那么基本上你就懂得如何往下写了,见代码:
import java.util.ArrayList;
import java.util.Random;
public class SingletonExpand {
//最多产生的实例数量
private static int maxNum=3;
private static SingletonExpand singletonExpand=new SingletonExpand();
//实例的id
private static int id=0;
//用来存放实例
private static ArrayList<SingletonExpand> list=new ArrayList<SingletonExpand>();
//私有的构造方法
private SingletonExpand(){
}
static{
for(int i=0;i<maxNum;i++){
list.add(new SingletonExpand());
}
}
//随机返回一个实例
public static SingletonExpand getSingleton(){
Random random=new Random();
id=random.nextInt(maxNum);
return list.get(id);
}
}
由于一段时间没写博客了,现在花了点时间写了一个单例模式的博客,大家要多多捧场啊。