【JAVA】:单例设计模型
# 单例设计模型
一、什么是单例设计模型 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
二、实际生活举例 (1)一个学校只有一个正校长。 (2)在一台电脑上有俩台打印机,但俩台打印机不能同时打印同一份文件。
三、优缺点 (1)在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。 (2)没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
四、实现方法
(1)懒汉式
public class Demo1 {
private static Demo1 demo=null;
private Demo1(){//构造方法私有化
}
public void sayHello(){
System.out.println("懒汉式(线程不安全):CSDN");
}
public static Demo1 getdemo(){
if(demo==null){
return new Demo1();
}
return demo;
}
public static void main(String[] args) {
Demo1 demo=Demo1.getdemo();
demo.sayHello();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
评价: 该设计模型由于没有加锁(synchronized),故线程不安全。
(2)懒汉式
public class Demo2 {
private static Demo2 demo=null;
private Demo2(){//构造方法私有化
}
public void sayHello(){
System.out.println("懒汉式(线程安全):CSDN");
}
public static synchronized Demo2 getdemo(){
if(demo==null){
return new Demo2();
}
return demo;
}
public static void main(String[] args) {
Demo2 demo=Demo2.getdemo();
demo.sayHello();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
评价: 该设计模型由于有加锁(synchronized),故线程安全。只有第一次获取该类实例化对象时需要创建对象,避免了内存的浪费,也支持多线程。但有个缺点是,加锁会影响效率。
(3)饿汉式
public class Demo3 {
private static Demo3 demo=new Demo3();
public static Demo3 getDemo3(){
return demo;
}
public void sayHello(){
System.out.println("饿汉式(线程安全):Hello CSDN");
}
public static void main(String[] args) {
Demo3 demo=Demo3.getDemo3();
demo.sayHello();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
评价: 但该类被加载完成后,该类的实例化对象就已经被创建了,这可能会导致了内存浪费。但该设计形式没有加锁(synchronized),故效率高,并且支持多线程。
(4)双检锁/双重校验锁
public class Demo4 {
private volatile static Demo4 demo;
private Demo4(){}
public void sayhello(){
System.out.println("双检锁/双重校验锁:Hello,CSDN");
}
public static Demo4 getdemo(){
if(demo==null){
synchronized (Demo4.class) {
if(demo==null){
demo=new Demo4();
}
}
}
return demo;
}
public static void main(String[] args) {
Demo4 demo=Demo4.getdemo();
demo.sayhello();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
评价: 安全且在多线程上能够保持较高性能。
(5)登记式/静态内部类
public class Demo5 {
//内部静态类
private static class Demo6{
private static final Demo5 demo=new Demo5();
}
private Demo5(){}
public void sayHello(){
System.out.println("登记式/静态内部类:Hello,CSDN");
}
public static final Demo5 getdemo(){
return Demo6.demo;
}
public static void main(String[] args) {
Demo5 demo=Demo5.getdemo();
demo.sayHello();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
评价: 该设计模型达到的目的以及性能上跟双重校验锁一样的。该模型是也是利用了Java 加载机制,来保证初始化 demo 时只有一个线程,与饿汉式不同。饿汉式是主要该类被装载就已经实例化了,而静态内部类是该类被装载后,该类的实例化对象并没有被创建,而是需要调用静态方法 getdemo()来获取对象。 这俩种设计形式相比,最后一种的设计模式是比较好的,当该类被加载后,并没有被实例化,当需要该对象是只要调用该类的静态内部类来实例化对象即可,减少内存资源的浪费。
(6)枚举法 枚举法与前面的五种相比较下,是有很大的优点的,设计更加严谨,实现也比较简单。为了介绍的更加详细在这里我不作介绍,但我会在下一篇博客进行详细介绍。