目录
- 单例模式概述
- 单例模式的结构与实现
- 单例模式的应用实例
- 饿汉式单例与懒汉式单例
- 单例模式的优缺点与适用环境
单例模式概述
Windows任务管理器:在正常情况下只能打开唯一一个任务管理器
如何保证一个类只有一个实例并且这个实例易于被访问?
- 全局变量:可以确保对象随时都可以被访问,但不能防止创建多个对象
- 让类自身负责创建和保存它的唯一实例,并保证不能创建其他实例,它还提供一个访问该实例的方法(单例模式)
单例模式的定义:
- 单例模式:确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。
- Singleton Pattern: Ensure a class has only one instance, and provide a global point of access to it.
- 对象创建型模式
要点:
- 某个类只能有一个实例
- 必须自行创建这个实例
- 必须自行向整个系统提供这个实例
单例模式的结构和实现
单例模式的结构:
单例模式只包含一个单例角色:
- Singleton(单例)
单例模式的实现:
- 私有的构造方法
- 静态私有的成员变量(自身类型)
- 静态公有的工厂方法
package com.zyt.designpatterns.singleton;
public class Singleton {
private static Singleton instance = null; // 静态私有成员变量
// 私有构造方法
private Singleton() {
}
// 静态共有工厂方法,返回唯一实例
public static Singleton getInstance() {
if (instance == null) {
return new Singleton();
}
return instance;
}
}
单例模式的应用实例
某软件公司承接了一个服务器负载均衡(Load Balance)软件的开发工作,该软件运行在一台负载均衡服务器上,可以将并发访问和数据流量分发到服务器集群中的多台设备上进行并发处理,提高了系统的整体处理能力,缩短了响应时间。由于集群中的服务器需要动态删减,且客户端请求需要统一分发,因此需要确保负载均衡器的唯一性,只能有一个负载均衡器来负责服务器的管理和请求的分发,否则将会带来服务器状态的不一致以及请求分配冲突等问题。如何确保负载均衡器的唯一性是该软件成功的关键,试使用单例模式设计服务器负载均衡器。
实例类图:
实例代码:
- LoadBalancer:负载均衡器类,充当单例角色
- Program:客户端测试类
饿汉模式与懒汉模式
- 饿汉式单例类(Eager Singleton)
实现代码:
package com.zyt.designpatterns.singleton;
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return instance;
}
}
模式分析:
在这个类被加载时,静态变量instance会被实例化,此时类的私有构造方法会被调用,单例类的唯一实例被创建。
- 懒汉式单例类(Lazy Singleton)
实现代码与双重检查锁定:
package com.zyt.designpatterns.singleton;
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {
}
synchronized public static LazySingleton getInstance() {
if (instance == null)
return new LazySingleton();
return instance;
}
}
注:在C#语言的实现中,使用双重检查锁定实现懒汉单例模式的多线程访问的解法方案。
饿汉式单例类与懒汉式单例类比较:
- 饿汉式单例类:无须考虑多个线程同时访问的问题;调用速度和反应时间优于懒汉式单例;资源利用效率不及懒汉式单例;系统加载时间可能会比较长
- 懒汉式单例类:实现了延迟加载;必须处理好多个线程同时访问的问题;需通过双重检查锁定等机制进行控制,将导致系统性能受到一定影响
单例模式的优缺点与适用环境
模式优点
- 提供了对唯一实例的受控访问
- 可以节约系统资源,提高系统的性能
- 允许可变数目的实例(多例类)
模式缺点
- 扩展困难(缺少抽象层)
- 单例类的职责过重
- 由于自动垃圾回收机制,可能会导致共享的单例对象的状态丢失
模式适用环境
- 系统只需要一个实例对象,或者因为资源消耗太大而只允许创建一个对象
- 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例