什么是设计模式?

  • 设计模式就是具体问题的最优解决方案(是一种经验)

单例设计模式

单例设计模式指的是:一个类只有一个对象(这个类只允许创建最多一个对象),哪怕是创建多次也是同一个对象,类似于Windows操作系统的任务管理器,无论打开多少次,但是都会只有一个窗口。

  • 单例设计模式的代码步骤:
  1. 将构造方法私有
  2. 提供一个静态的变量,用于保存该类的对象(根据创建对象的时机不同,可以分为懒汉和饿汉)
  3. 提供一个静态的方法,用于让调用者通过方法获取对象

饿汉式单例设计模式

在类一加载的时候就创建好对象了,这种单例设计是最常用的,也是最简单的。

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
package com.xlkh.demo04_designMode;

public class A {
// 单例设计模式-饿汉式(在类一加载的时候,立刻创建出该类的对象
// 1,将构造方法私有(防止胡乱造对象
private A(){}

// 2. 设计一个静态的该类型的变量,并且立刻创建出对象(构造方法虽然是私有,但只是对外界私有
private static A a = new A();

// 3. 提供一个静态方法(方法名随意),让调用者通过该方法获取A类的对象
public static A getA(){
// 返回提前创建好的A类型的对象
return a;
}
}

// TestA
package com.xlkh.demo04_designMode;

public class TestA {
public static void main(String[] args) {
// 1,尝试创建对象
//A a = new A(); // 报错-A的构造方法私有

// 2,只能通过A类提供的静态方法创建对象,且每次获取的都是同一个对象
for (int i = 0; i < 10; i++) {
System.out.println(A.getA());
}
}
}

饿汉式优点

非常安全,即使在多线程下也能保证安全。

饿汉式缺点

非常安全,即使在多线程下也能保证安全。

懒汉式单例设计模式

懒汉式的优缺点:

  • 优点:
    • 可以让创建对象饿时机尽可能晚,从而节约程序内存。
  • 缺点:
    1. 多线程的时候,不安全(一个类可以有好几个对象)。
    2. 程序运行的性能较差。
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
38
39
40
41
42
43
44
package com.xlkh.demo04_designMode;
/*
单例设计模式之 - 懒汉式
第一次获取对象的时候,才开始创建对象
*/
public class Lazybones {
// 1, 将构造方法私有化
private Lazybones(){};

// 2, 创建静态变量,用于保存当前类的对象
private static Lazybones l;

// 3, 提供一个公共的静态方法用于返回该类的实例
public static Lazybones getLazybones(){
// 判断 是不是第一次调用这个方法
if (l == null){
l = new Lazybones();
}
// 如果不是第一次调用,说明之前调用过了,这次直接返回实例就好。
return l;
}
}

// TestLazybones
package com.xlkh.demo04_designMode;
/*
测试单例模式-懒汉式 方法
*/
public class TestLazybones {
public static void main(String[] args) {
// 测试懒汉式的获取对象-- 没有发现bug
// for (int i = 0; i < 10; i++) {
// System.out.println(Lazybones.getLazybones());
// }

// 通过多线程创建对象 -- 发现bug
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(Lazybones.getLazybones());
}).start();
}
}
}

懒汉式获取对象的bug演示

在使用多线程的情况下,违背了单例设计模式只有一个对象的原则。

Summary:

最重要的是记住那三步:

  • 首先将构造方法设为私有-防止调用者胡乱造对象。
  • 创建私有的静态变量,用于保存类的对象。
  • 创建公共的静态方法,让调用者通过类名.方法名获取对象。