单例模式是比较简单的一个模式,项目中也经常用得到。
实现细节
将类的构造方法设置为私有的(private),通过个公有的(public)的方法来获取类的实例。
代码示例
public class Singleton {
private static Singleton singleton= null;
public static Singleton getSingleton(){
if(singleton==null){
singleton = new Singleton();
}
return singleton;
}
private Singleton(){
//System.out.println("new singleton");
}
}
上边的这个例子在高并发的情况下可能会出现同步问题,如果一个线程在完成if判断但是对象未能创建完成的时候另一个线程也进行if判断,那么内存中就会产生多个实例,为了保证线程安全,可以采用以下两种方法。
第一种做法,直接实例化类
public class Singleton {
private static Singleton singleton= new Singleton();
public static Singleton getSingleton(){
return singleton;
}
private Singleton(){
//System.out.println("new singleton");
}
}
第二种方法,对if判断加锁
public class ConcurrentSingleton {
private static ConcurrentSingleton singleton = null;
private ConcurrentSingleton(){
//System.out.println("new singleton");
}
public static ConcurrentSingleton getSingleton(){
if(singleton==null){
createSingleton();
}
return singleton;
}
private static synchronized void createSingleton() {
if(singleton==null){
singleton = new ConcurrentSingleton();
}
}
}
单例模式的优缺点
优点是在内存中只存在一个实例,减少内存开销和创建、销毁对象的性能损耗,可以避免对资源的多种占用,优化和共享资源访问。
缺点是扩展比较困难。
单例模式的扩展
如果一个类只能生成限定个数的实例,可以通过扩展单例来实现
代码实例
public class MultiInstanceSingleton {
private static int maxInstanceSize = 5;
private int number = 0;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
private static Vector<MultiInstanceSingleton> vec = new Vector<MultiInstanceSingleton>();
private MultiInstanceSingleton(){
}
private MultiInstanceSingleton(int num){
this.number = num;
}
private static synchronized MultiInstanceSingleton createInstance(){
return new MultiInstanceSingleton(vec.size());
}
public static MultiInstanceSingleton getInstance(){
MultiInstanceSingleton instance = null;
if(vec.size()<maxInstanceSize){
instance = createInstance();
vec.add(instance);
}else{
int num = new Random().nextInt(maxInstanceSize);
instance = vec.elementAt(num);
}
return instance;
}
public void doSomething(){
System.out.println("我是"+this.number+"号");
}
public static void main(String[] args) {
for(int i=0;i<50;i++){
getInstance().doSomething();
}
}
}