首页 > 代码库 > 读秦小波《设计模式之禅》 -- 单例模式

读秦小波《设计模式之禅》 -- 单例模式

      新年第一天,在这里首先要祝大家新年快乐!

      这篇文章中,介绍的是非常重要,也是非常常用的一种设计模式 -- 单例模式。例如,我们在电脑上登录QQ的时候,同一个QQ号码就只能登录一次,而不可能出现一个号码可以登录两次的情况;再好像我现在听歌用的播放器,我也只能打开它一次,当它在运行的时候,我不能够同时运行两个播放器客户端。。。等等的这些模式都是单例的,即它能保证一个类就只有一个实例对象。

      这里运用书中的例子去解释构造单例的方法。

      一个国家需要有一个皇帝,并且这个皇帝就只能有一个,那么,很显然,它是单例的。我们需要构造一个皇帝类,且这个皇帝类只能有一个实例对象,那么,这里就会出现一个限制,即这个类的构造方法需要是私有的(private),否则,我们可以任意的生成对象。且这个类需要有一个静态方法(static),当我们需要这个类的对象时,就可以利用这个方法去获取类对象。

      好吧,看下具体的实现吧:

public class __Q_Y_Emperor {

	/*这样设计可以保证它是线程安全的*/
	private static __Q_Y_Emperor _Emperor = new __Q_Y_Emperor();
	
	private __Q_Y_Emperor()
	{
		
	}
	
	public static __Q_Y_Emperor __Q_Y_GetInstance()
	{
		return _Emperor;
	}
	
	public static void __Q_Y_Talk()
	{
		System.out.println("i am Qinyi Zhang...");
	}
}
      这个类的实现就是利用到单例模式,当然,这里只是单例模式的一种实现方式。

      我们需要一个测试函数,测试下这个单例模式是否好用,这里,场景是有几个大臣找皇帝,然后,每一个大臣找到的都是同一个皇帝。

public class __Q_Y_EmperorMain {

	/**
	 * @param args
	 */
	@SuppressWarnings("static-access")
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int _Minister = 5;
		
		for (int i = 0; i != _Minister; ++i)
		{
			/*获取的实例对象都是同一个*/
			__Q_Y_Emperor _Emperor = __Q_Y_Emperor.__Q_Y_GetInstance();
			
			_Emperor.__Q_Y_Talk();
		}
	}

}
      我们运行下这个主函数,得到如下的结果:

i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
i am Qinyi Zhang...
      下面,看下类图是怎样的,很简单,没有继承关系之类的

技术分享

      书中从单例模式又引申出了一个叫 “多例模式” 的设计方法,即一个类能产生多个对象,但是对象的个数是有限制的。

      也同样是皇帝的例子,只是这个例子中出现了多个皇帝,每个大臣可能找到的是不同的皇帝。

      好吧,这个也是很容易实现的:

public class __Q_Y_MultiEmperor {

	private final static int _MaxNumOfEmperor = 3;
	
	private static ArrayList<String> _EmperorName = new ArrayList<String>();
	
	private static ArrayList<__Q_Y_MultiEmperor> _EmperorList = new ArrayList<>();
	
	private static int _CurrentNumOfEmperor = 0;
	
	private __Q_Y_MultiEmperor()
	{
		
	}
	
	private __Q_Y_MultiEmperor(String _name)
	{
		_EmperorName.add(_name);
	}
	
	static
	{
		/*多例模式,对象个数是有限制的*/
		for (int i = 0; i != _MaxNumOfEmperor; ++i)
		{
			_EmperorList.add(new __Q_Y_MultiEmperor("num " + (i + 1)));
		}
	}
	
	public static __Q_Y_MultiEmperor __Q_Y_GetInstance()
	{
		Random _randrom = new Random();
		
		_CurrentNumOfEmperor = _randrom.nextInt(_MaxNumOfEmperor);
		
		return _EmperorList.get(_CurrentNumOfEmperor);
	}
	
	public static void __Q_Y_Talk()
	{
		System.out.println(_EmperorName.get(_CurrentNumOfEmperor));
	}
}
      测试函数:

public class __Q_Y_MultiMain {
	
	/**
	 * @param args
	 */
	@SuppressWarnings("static-access")
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int _Minister = 10;
		
		for (int i = 0; i != _Minister; ++i)
		{
			__Q_Y_MultiEmperor _Emperor = __Q_Y_MultiEmperor.__Q_Y_GetInstance();
			
			_Emperor.__Q_Y_Talk();
		}
		
	}

}
      类图:

技术分享

      最后,运行下这个例子吧:

num 3
num 2
num 2
num 2
num 3
num 1
num 2
num 2
num 1
num 1



读秦小波《设计模式之禅》 -- 单例模式