第一章 单例模式
1.1简介
有些系统中,为了节省内存资源,保证数据的一致性,对某些类要求只能创建一个实例。这就是单例模式。
1.2模式定义
一个类只有一个实例,且该类能够自行创建这个实例的一种模式,例如windows的任务管理器设置为单例模式,可以避免打开多个任务管理器窗口造成的内存资源浪费,或者多个窗口显示内容不一致的情况。
1.3单例模式的特点
(1)单例类只有一个实例对象
(2)该实例对象必须由单例类自行创建
(3)单例类对外提供一个访问该单例的全局访问点
1.4模式的结构与实现
单例模式是设计模式中最简单的模式之一。通常,普通类的构造函数是public的,外部类可以通过new来生成多个实例。但单例模式的构造方法是private的,外部类无法调用该构造函数,也就无法生成多个实例。
这时,类自身必须定义一个静态私有实例,并向外提供一个静态公有函数用于创建或获取该静态私有实例。
- 模式结构
主要角色有:
(1)单例类:包含一个实例,且能自行创建这个实例
(2)访问类:使用单例的类
- 模式的实现
Singleton模式有两种实现形式
第1种 懒汉式
类加载时没有生成单例,只有当第一次调用getInstance方法时才创建单例。
实例代码:
public class LazySingleton{
// volatile保证instance在所有线程中同步
private static volatile LazySingleton instance = null;
private LazySingleton(){} // private避免类在外部被实例化
public static synchronized LazySingleton getInstance(){
// getinstance方法前加同步
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
注意:编写的多线程程序,需要使用关键字volatile和synchronized,否则将存在线程非安全的问题。但这样每次访问时都需要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。
第2种 饿汉式
类一旦加载就创建一个单例,保证在调用getInstance方法之前就有单例存在。
public class HungrySingleton{
private static final HungreySingleton instance = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return instance;
}
}
注意:饿汉式单例在类创建的时候就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。
1.5模式的应用实例
懒汉式单例模式模拟产生美国当今总统对象
分析:每一届任期内,美国的总统只有一人,所以本实例适合用单例模式实现。
public class LazySingleton{
public static void main(String[] args){
President zt1 = President.getInstance();
zt1.getName();
President zt2 = President.getInstance();
zt2.getName();
if(zt1 == zt2){
System.out.println("他们是同一人!");
}else{
System.out.println("他们不是同一人!");
}
}
}
class President{
private static volatile President instance = null;
private President(){
System.out.println("产生一个总统!");
}
public static synchronized President getInstance(){
if(instance == null){
instance = new President();
}
else{
System.out.println("已经有一个总统,不能产生新总统");
}
return instance;
}
public void getName(){
System.out.println("我是美国总统:特朗普")
}
}
程序运行结果:
产生一个总统
我是美国总统:特朗普
已经有一个总统,不能产生新总统
我是美国总统:特朗普
他们是同一人!
1.6模式的应用场景
(1)某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等
(2)对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如Web中的配置对象、数据库的连接池等。
(3)某类需要频繁实例化,儿创建的对象又频繁的被销毁的时候,如多线程的连接池、网络连接池等。
1.7模式的扩展
单例模式可以扩展为有限的多例模式,这种模式可生成有限个实例并保存在ArrayList中,客户需要时可随机获取,结构图如下: