tonglin0325的个人主页

Java单例设计模式

单例模式(Singleton Pattern)是Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。 这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

1.没有使用单例:重复调用会创建多个对象#

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
package java_basic;

class Singleton{
public Singleton(){
}

public void print(){
System.out.println("Hello Word");
}
}

public class singleton {

public static void main(String[] args) {
Singleton s1 = new Singleton();
Singleton s2 = new Singleton();
Singleton s3 = new Singleton();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
s1.print();
s2.print();
s3.print();
}

}

 

2.饿汉式单例:(一定是安全的,只有一份对象)
#

1.构造器私有化

2.声明私有的静态属性,同时创建该对象

3.对外提供访问属性的静态方法,确保该对象存在。

写法1:初始化就加载#

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
package java_basic;

class Singleton{
private static Singleton instance = new Singleton();//声明私有的静态属性,同时创建该对象
private Singleton(){ //构造函数私有化
}

public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在
return instance;
}

public void print(){
System.out.println("Hello Word");
}
}


public class singleton {

public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
Singleton s3 = Singleton.getInstance();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
s1.print();
s2.print();
s3.print();
}

}

可以看到输出的hashCode只有一个,证明new出的对象是同一个

写法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
package java_basic;

class Singleton{
// 再定义一个Single类,Single类在使用的时候加载,懒加载
  private static class Single{
private static Singleton instance = new Singleton(); //声明私有的静态属性,同时创建该对象
}

private Singleton(){ //构造函数私有化
}

public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在
return Single.instance;
}

public void print(){
System.out.println("Hello Word");
}
}

public class singleton {

public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
Singleton s3 = Singleton.getInstance();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
s1.print();
s2.print();
s3.print();
}

}

3.懒汉式单例:(不一定安全,确保只有一份对象需要synchronized)
#

1.构造器私有化

2.声明私有的静态属性

3.对外提供访问属性的静态方法,确保该对象存在。

写法1,多线程下不安全#

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
package java_basic;

class Singleton{ //懒汉模式,多线程下不安全
private static Singleton instance; //声明私有的静态属性,但是不创建该对象
private Singleton(){ //构造函数私有化
}

public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在
if(instance == null){
instance = new Singleton();
}
return instance;
}

public void print(){
System.out.println("Hello Word");
}
}

public class singleton {

public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
Singleton s3 = Singleton.getInstance();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
s1.print();
s2.print();
s3.print();
}

}

 

写法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
package java_basic;

class Singleton{ //懒汉模式,加锁
private static Singleton instance; //声明私有的静态属性,但是不创建该对象
private Singleton(){ //构造函数私有化
}

public static Singleton getInstance(){ //对外提供访问属性的静态方法,确保该对象存在
if(instance == null){
synchronized(Singleton.class){//加锁
if(null == instance){
instance = new Singleton();
}
}
}
return instance;
}

public void print(){
System.out.println("Hello Word");
}
}

public class singleton {

public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
Singleton s3 = Singleton.getInstance();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
s1.print();
s2.print();
s3.print();
}

}

懒汉式参考:Java学习之线程锁–单例模式写法–synchronized

4.枚举单例:(线程安全)#

1
2
3
4
5
6
7
8
9
10
11
12
public enum Singleton{

//定义1个枚举的元素,即为单例类的1个实例
INSTANCE;

// 隐藏了1个空的、私有的 构造方法
// private Singleton () {}

}
// 获取单例的方式:
Singleton singleton = Singleton.INSTANCE;

 

《大话设计模式》P232

P

《剑指Offer》P51