设计模式一 单例模式

单例模式是一个很常用的创造型模式,其主要目的是控制生成对象的唯一性。在java中实例化对象的方法主要通过new(还有反射、clone等,本篇不讨论)。为了限制new方法的使用,首先要将单例类的构造函数设置为private,如此客户端就无法直接调用构造函数来new对象了。
   下图是单例模式的一个简单类图:

通过静态方法getInstance获取对象实例,一种方式是通过static初始化模块来实例化这个单例对象,这种方式在该类被加载时实例,由于类的初始化过程是唯一的所以这种单例模式也是线程安全的。
public class OneClass {
	private static OneClass instance=new OneClass();
	private OneClass(){
		
	}
	public static OneClass getInstance(){
		return instance;
	}
	public void func(){
		System.out.println(this.toString());
	}
	
	public static void main(String args[]){
		OneClass one=OneClass.getInstance();
		one.func();
	}
}

另外一种方式在第一次获取getInsatnce时进行实例化,这种方式明显在多线程情况下需要对getInstance进行加锁控制。下面这段代码是未对getInstance进行加锁,由于构造函数的2秒暂停,可以发现最终结果子线程和main线程打印出的对象id是不同的。解决的方法很简单对getInstance方法添加synchronized关键字即可。
public class OneClass {
	private static OneClass instance=null;
	private OneClass(){
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public  static OneClass getInstance(){
		if(instance==null){
			instance=new OneClass();
		}
		return instance;
	}
	public void func(){
		System.out.println(this.toString());
	}

	public static void main(String args[]){
		new Thread(new Runnable(){
			public void run() {
				OneClass two=OneClass.getInstance();
				two.func();
			}
		}).start();;
		OneClass one=OneClass.getInstance();
		one.func();
	}
}


当然也可以将锁移动到内部具体实例化的代码段,来缩小加锁区域,其中需要额外注意的是在获取到锁之后需要再次判断下instance引用是否为空(因为线程获得到锁之后会继续执行下去):
	public  static OneClass getInstance(){
		if(instance==null){
			synchronized(OneClass.class){
				if(instance==null){
					instance=new OneClass();
				}
			}
		}
		return instance;
	}

最后给出一种最简洁的写法,通过内部类来获取单例,由于内部类在调用getInstance的时候才会被初始化,因此达到懒汉模式:
public class OneClassBest {
	private OneClassBest(){
	}
	private static class ClassHandle{
		private  static OneClassBest oneInstace=new OneClassBest();
	}
	public   static OneClassBest getInstance(){
		return ClassHandle.oneInstace;
	}
}

猜你喜欢

转载自fobject.iteye.com/blog/2271923