设计模式 | 单例模式

Posted 数据与共享

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式 | 单例模式相关的知识,希望对你有一定的参考价值。

 单例,即:只有一个实例。  通过单例模式可以保证,一个系统或应用中, 类的实例只有一个。通过使用单例模式,减小了系统的开销,并且有利于Java垃圾回收。

1.懒汉模式 

缺点:许多博客中说,多线程下会有异常发生,可是经过我的测试,并没有发现异常情况。

实例类:SingleExample

 1private static SingleExample singleExample = null;
2private static int i = 0;
3private SingleExample({
4}
5public static SingleExample getInstance({
6    if (singleExample == null) {
7        i++;
8        System.out.println("i=" + i);
9        singleExample = new SingleExample();
10    }
11    return singleExample;
12}

测试类:

1public static void main(String[] args) {
2    SingleExample single = SingleExample.getInstance();
3    SingleExample single2 = SingleExample.getInstance();
4    SingleExample single3 = SingleExample.getInstance();
5}

Test测试输出:i = 1;说明三次调用只创建了一个对象。单例模式实现。

懒汉模式 多线程举例:

实例类:SingleThread

 1private static SingleThread single;
2private  static int i = 0;
3private SingleThread({
4}
5public static  SingleThread getSingle({
6    if (single == null) {
7        i++;
8        System.out.println("i=" + i);
9        single = new SingleThread();
10    }
11    return single;
12}
13@Override
14public void run(
{
15    // TODO Auto-generated method stub  
16}

测试方法:

1public static void main(String[] args) {
2    SingleThread single1 = SingleThread.getSingle();
3    SingleThread single2 = SingleThread.getSingle();
4    SingleThread single3 = SingleThread.getSingle();
5    SingleThread single4 = SingleThread.getSingle();
6    Thread thread1 = new Thread(single1);
7    Thread thread2 = new Thread(single2);
8    Thread thread3 = new Thread(single1);
9    Thread thread4 = new Thread(single2);
10    thread1.start();
11    thread2.start();
12    thread3.start();
13    thread4.start();
14}

Test测试输出:i = 1;说明三次调用只创建了一个对象。单例模式实现。多线程下也是安全的,或者我的测试方法不对,希望大家集思广益,指出我的错误之处。

2.饿汉模式

类在装载时就进行了实例化,这一点不如懒汉模式。

实例类:HungryPattern

1private static HungryPattern hunPattern = new HungryPattern();
3private HungryPattern({
4}
5public static HungryPattern getHunPattern({
8    return hunPattern;
9}


3.静态内部类

实例类:StaticInnerClass

1private StaticInnerClass() {
2}
3private static class SinglePattern {
4    private static final StaticInnerClass singlePa = new StaticInnerClass();
5}
6public static final StaticInnerClass getInnerClass() {
7    return SinglePattern.singlePa;
8}


4.双重检查

Double Check

实例类:DoubleCheck

 1private static volatile DoubleCheck doubleCheck;
2private DoubleCheck() {
3};
4public static DoubleCheck getIntance() {
5    if (doubleCheck == null) {
6        synchronized (DoubleCheck.class) {
7            if (doubleCheck == null) {
8                doubleCheck = new DoubleCheck();
9            }
10        }
11    }
12    return doubleCheck;
13}
14@Override
15public void run() {
16    // TODO Auto-generated method stub
17}


5.enum实现单例模式

为什么用枚举:

(1)enum 继承自Enum,而Enum是被final修饰的类。

(2)final修饰,这意味着其本身就是一个单例类型,并且其线程安全。

(3)并且其实现过程简单,代码的可读性更强。

实例类:Instance1

1public static void show({
2    System.out.println("我是Instance1");
3}

枚举类:Instance

1instance;
2private Instance1 ins1 = new Instance1();
3public Instance1 getInstance() {
4    return ins1;
5}

测试类:TestInstance,运行结果为ture。

1public static void main(String[] args{
2 Instance1 ins1 = Instance.instance.getInstance();
3 Instance1 ins2 = Instance.instance.getInstance();
4 System.out.println(ins1==ins2);
5}

使用enum有没有很爽,我这个例子可能没有体现出线程安全,代码简洁等特性。但是请相信我,越来越多的人会发现enum是多么好用,而static final这种机械写法是如何的冗杂。我司使用enum的频率已成上升趋势。



说明:单例模式的u构造很简单,但是在合适的应用场景使用有点不知所措,尤其是设计多线程时。另外我终于忍不了AV画质的截图,使用了Md2All工具对代码进行了整理。



 





以上是关于设计模式 | 单例模式的主要内容,如果未能解决你的问题,请参考以下文章

常用代码片段

性能比较好的单例写法

你熟悉的设计模式都有哪些?写出单例模式的实现代码

单例模式以及静态代码块

设计模式之单例模式

设计模式之单例模式