单例模式

模式定义

  • 单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
  • 单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。

饿汉式单例模式

由于在定义静态变量的时候实例化单例类,因此在类加载的时候就已经创建了单例对象;当类被加载时,静态变量 instance 会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建。

1
2
3
4
5
6
7
8
9
10
11
12
public class EagerSingleton {
//1.将构造方法私有化,不允许外部直接创建对象
private EagerSingleton(){

}
//2.创建类的唯一实例,使用private static修饰
private static EagerSingleton instance=new EagerSingleton();
//3.提供一个用于获取实例的方法,使用public static修饰
public static EagerSingleton getInstance(){
return instance;
}
}

懒汉式单例模式

懒汉式单例在第一次调用 getInstance() 方法时实例化,在类加载时并不自行实例化,这种技术又称为延迟加载(Lazy Load)技术。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class LazySingleton {
//1.将构造方式私有化,不允许外边直接创建对象
private LazySingleton(){

}
//2.声明类的唯一实例,使用private static修饰
private static LazySingleton instance;
//3.提供一个用于获取实例的方法,使用public static修饰
public static LazySingleton getInstance(){
if(instance==null){
instance=new LazySingleton();
}
return instance;
}
}

该懒汉式单例类实现静态工厂方法时使用了同步化机制,以处理多线程环境。同时,由于构造函数是私有的,因此该类不能被继承。

饿汉式单例与懒汉式单例类比较

  • 饿汉式单例类在自己被加载时就将自己实例化。单从资源利用效率角度来讲,这个比懒汉式单例类稍差些。从速度和反应时间角度来讲,则比懒汉式单例类稍好些。
  • 懒汉式单例类在实例化时,必须处理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过同步化机制进行控制。

模式优缺点

单例模式的优点

  • 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
  • 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
  • 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。

单例模式的缺点

  • 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
  • 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
  • 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。

多例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.util.ArrayList;

public class Multiton {
//maxNum:定义最多能产生的实例数量
private static int maxNum = 3;
//定义一个列表,容纳所有的实例
private static ArrayList<Multiton> MultitionList = new ArrayList<Multiton>();
//当前实例序列号
private static int countNum = 0;
private Multiton(){
}

//懒汉模式,生产实例
public static Multiton getInstance(){
if(countNum<maxNum){
MultitionList.add(new Multiton());
System.out.println("生产实例"+(countNum+1));
}
try {
return MultitionList.get(countNum++);
} catch (Exception e) {
// TODO: handle exception
System.out.println("超过最多能产生的实例数量:"+maxNum);
}
return null;
}

public static Multiton getInstance(int num){
try {
return MultitionList.get(num);
} catch (Exception e) {
// TODO: handle exception
System.out.println("没有该实例"+(num+1));
}
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TestofMutition {
public static void main(String[] args) {
// TODO Auto-generated method stub
int Num = 5;
Multiton s;
for(int i=0; i<Num ;i++){
s = Multiton.getInstance();
}
for(int i=0; i<Num ;i++){
s = Multiton.getInstance(i);
}
}
}
文章目录
  1. 1. 模式定义
  2. 2. 饿汉式单例模式
  3. 3. 懒汉式单例模式
  4. 4. 饿汉式单例与懒汉式单例类比较
  5. 5. 模式优缺点
    1. 5.1. 单例模式的优点
    2. 5.2. 单例模式的缺点
  6. 6. 多例模式

20160528-DesignPattern-5/

本页二维码