官方的介绍
GOF的书中,单例模式最早的定义如下:
单例模式属于创建型模式
单例模式(Singleton) 允许存在一个或仅存在一个给定类的实例。它提供一种机制让任何实体都可以访问该实例。
我的理解:单例模式类似于全局变量或全局函数的角色,可以使用它来代替全局变量。
单例模式的职责
- 保证一个类只有一个实例
- 为该实例提供一个全局访问节点
UML类图
应用场景
单例模式更多是在程序一开始进行初始化时使用的
- 表示全局唯一类 :比如配置信息类。在系统中,我们只有一个配置文件,当文件加载到内存之后,以对象的形式存在,所以理所当然只有一份。在一个系统中要求一个类只有一个实例时才应当使用单例模式。
- 系统某些资源有限:比如控制某些共享资源(例如数据库或者文件)的访问权限。
class Helper
{
// 私有静态属性 用于保存实例
private static $instance;
// 私有构造 防止外部创建实例
private function __construct(){}
// 公有方法 用于获取当前实例
public static function getInstance(): Helper
{
if (self::$instance == null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 格式化价格
* @param $number
* @param $accuracy
* @return string
*/
public function formatPrice($number, $accuracy): string
{
return number_format($number, $accuracy, '.', '');
}
// 防止复制实例
private function __clone() {}
}
// 辅助工具类的使用
$instance = Helper::getInstance();
$price = $instance->formatPrice(2,2);
实现单例模式的方式
三私一公
1. 私有静态属性用于保存实例
2. 私有构造方法用于避免外部通过new创建实例
3. 私有克隆方法用于防止实例复制
4. 公有方法,提供外部调用获取实例
优势
1. 对有限资源的合理利用,保护有限的资源,防止资源重复争抢。
2. 更高内聚的代码组件,能提升代码复用性。
3. 具备全局唯一访问点的权限控制,方便按照统一规则管控权限。
劣势
1. 作为全局变量使用时,引用的对象越多,代码修改影响的范围也越大
2. 作为全局变量时,在全局变量中使用状态变量时,会造成加/解锁的性能损耗。
3. 即便扩展多实例,但耦合性依然很高,因为隐蔽了不同对象之间的调用关系
4. 不支持有参数的构造函数。