一、需求背景
有些类在实际应用场景中只需要一个具体对象来管理,如线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表的对象、日志对象、充当打印机、显卡等设备的驱动程序的对象。事实上这类对象只能有一个实例,如果制造出多个实例,就会导致很多问题产生,如程序的行为异常、资源使用过量,或者不一致的结果。
单例模式的作用相当于全局变量,但全局变量必须在程序一开始就创建好对象,一但当前对象很耗费资源,而当前数据未实际用到这个对象,就有些浪费。
二、实现要点
1、必须将构造函数定义为private的,禁止外部直接调用构造函数,这样就只能走全局访问点来这样一条路径来获取当前类对象;
2、需要定义一个静态类成员变量,在第一次外部访问类对象时构建,以后再获取,直接使用,直到程序声明周期结束;
3、需要定义一个public的静态方法作为获取类对象的方法;
三、存在问题
全局访问点方法实现过程中会遇到多线程问题,导致设计模式初期预想的效果会失效;
三、例子代码
namespace ChocolateBoilerCleanWater
{
/// <summary>
/// 巧克力工厂---原始类
/// </summary>
public class ChocolateBoiler
{
private bool empty;
private bool boiled;
/// <summary>
/// 构造函数改为私有,禁止外部直接创建对象
/// </summary>
public ChocolateBoiler()
{
empty = true;
boiled = false;
}
public bool isEmpty()
{
return empty;
}
public bool isBoiled()
{
return boiled;
}
public void fill()
{
if (empty)
{
empty = false;
boiled = false;
}
}
public void drain()
{
if (!isEmpty() && isBoiled())
{
empty = true;
boiled = false;
}
}
public void boil()
{
if (!isEmpty() && !isBoiled())
{
boiled = true;
}
}
}
}
namespace ChocolateBoilerSingleton
{
/// <summary>
/// 巧克力工厂-单例模式的初次实现
/// </summary>
public class ChocolateBoiler
{
private bool empty;
private bool boiled;
private static ChocolateBoiler m_ChocolateBoiler;
/// <summary>
/// 定义全局唯一访问点
/// </summary>
/// <returns></returns>
public static ChocolateBoiler getInstance()
{
if(null == m_ChocolateBoiler)
m_ChocolateBoiler = new ChocolateBoiler();
return m_ChocolateBoiler;
}
/// <summary>
/// 构造函数改为私有,禁止外部直接创建对象
/// </summary>
private ChocolateBoiler()
{
empty = true;
boiled = false;
}
public bool isEmpty()
{
return empty;
}
public bool isBoiled()
{
return boiled;
}
public void fill()
{
if (empty)
{
empty = false;
boiled = false;
}
}
public void drain()
{
if (!isEmpty() && isBoiled())
{
empty = true;
boiled = false;
}
}
public void boil()
{
if (!isEmpty() && !isBoiled())
{
boiled = true;
}
}
}
}
namespace ChocolateBoilerSingletonConsiderMultiThread
{
/// <summary>
/// 巧克力工厂--考虑多线程的单例模式实现
/// </summary>
public class ChocolateBoiler
{
private bool empty;
private bool boiled;
private static object _lock = new object();
private static ChocolateBoiler m_ChocolateBoiler;
/// <summary>
/// 定义全局唯一访问点
/// </summary>
/// <returns></returns>
public static ChocolateBoiler getInstance()
{
if (null == m_ChocolateBoiler)
{
lock (_lock)
{
if (null == m_ChocolateBoiler)
{
m_ChocolateBoiler = new ChocolateBoiler();
}
}
}
return m_ChocolateBoiler;
}
/// <summary>
/// 构造函数改为私有,禁止外部直接创建对象
/// </summary>
private ChocolateBoiler()
{
empty = true;
boiled = false;
}
public bool isEmpty()
{
return empty;
}
public bool isBoiled()
{
return boiled;
}
public void fill()
{
if (empty)
{
empty = false;
boiled = false;
}
}
public void drain()
{
if (!isEmpty() && isBoiled())
{
empty = true;
boiled = false;
}
}
public void boil()
{
if (!isEmpty() && !isBoiled())
{
boiled = true;
}
}
}
}