单件模式——Singleton Pattern

单件模式

Java程序的基本单位是类
大概在学习了Java后,都会很自然的写下这样一个简单的类,如
public class Example
{
	public Example(){}
	/*------any other code------*/
	public static void main(String args[])
	{
		System.out.println("Hello Java");
	}
}
我们都知道构造器的定义比较简单,无返回类型以及名称需要与类名一样
如果要给构造器加上访问说明符,我们也会很自然的加上public
而我们却很少或者不可能会这样写
public class Example
{
	//构造器的访问说明符为private
	private Example(){}
	/*------any other code------*/
	public static void main(String args[])
	{
		System.out.println("Hello Java");
	}
}
当我们在其它的类中试图实例化Example类时就会出现错误
public class Example
{
	private Example(){}
}
class ExampleDemo
{
	public static void main(String args[])
	{
	    //程序出现错误,无法通过编译
		Example e = new Example();
		//含有私有构造器的类只能在自身实例化
	}
}
为了实例化含有私有构造器的Example类,我们可以这样做
public class Example
{
	private Example(){}
	/*------any other code------*/
	public static void main(String args[])
	{
		Example e = new Example();
	}
}
或者直接将Example类的实例定义为成员变量
public class Example
{
	private Example e = new Example();
	private Example(){}
	/*------any other code------*/
	public static void main(String args[]){}
}
现在我们知道含有私有构造器的类只能在自身内实例化而不能在其它类中实例化
那么我们就会想到,使用这种方法我们就可以在这种含有私有构造器的类中定义一个唯一的实例
单件模式:确保一个类只有一个实例,并提供一个全局访问点
代码演示:
public class Singleton
{
	private static Singleton singleton = new Singleton();
	private Singleton(){}
	public static Singleton getSingleton()
	{
		return singleton;
	}
}
public class SingletonDemo
{
	public static void main(String args[])
	{
		Singleton.getSingleton();
	}
}
事实上,我们可能并不急切的需要在一开始的时候就实例化,我们更多的在运行时才进行实例化
public class Singleton
{
	private static Singleton singleton;
	private Singleton(){}
	public static Singleton getSingleton()
	{
		if(singleton==null)
			singleton = new Singleton();
		return singleton;
	}
}
但是,使用上面的方法我们还需要考虑到多线程的程序,上面的代码会出现问题
因为在一开始的时候并没有进行实例化,所以使用多线程时就可能造成多个对象的产生
为了解决多个对象的产生这一问题,我们需要将synchronized关键字加到方法getSingleton()中
这样,每个线程在进入这个方法之前就先要等待其它的线程离开,从而实现同步
class Singleton
{
	private static Singleton singleton ;
	private Singleton(){}
	public static synchronized Singleton getSingleton()
	{
		if(singleton==null)
			singleton = new Singleton();
		return singleton;
	}
}
只在方法getSingleton()前加上关键字synchronized的办法既简单又有效
然而我们只有在第一次执行这个方法时才真正需要实现同步这个方法
以后的每一次调用都会造成不必要的累赘,因此这个办法并不适用于经常需要调用这个方法的程序
为了解决这个问题,我们除了可以在一开始就将该类实例化外,还可以使用“ 双重检查 加锁”的
我们可以清楚的知道,该方法只在第一次调用时实现同步,这样解决问题的办法就简单了
我们只需要使用一个if语句先检查是否已经实例化了,如果没有才进行同步,代码如下
public class Singleton
{
	//关键字volatile使多个线程能正确处理singleton
	private volatile static Singleton singleton;
	private Singleton(){}
	public static Singleton getSingleton()
	{
		if(singleton==null)
		{
			synchronized(Singleton.class)
			{
				if(singleton==null)
				{
					singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}
使用单件模式可以使程序中一个类只有一个实例
单件模式是所以设计模式中最简单的一个
当我们设计的对象不能或不想被多次实例化的时候就可以使用单件模式
实现单件模式需要定义一个私有构造器、一个静态变量和一个静态方法

设计模式的应用:缓存、数据库连接池

参考书籍《Head First 设计模式》










你可能感兴趣的:(java,设计模式,Singleton,Pattern)