数学建模社区-数学中国

标题: 浅谈单例模式的实现方式 [打印本页]

作者: 杨利霞    时间: 2020-3-30 17:20
标题: 浅谈单例模式的实现方式
浅谈单例模式的实现方式1 N& C8 v9 C9 n/ u! N
单例模式(来自菜鸟教程)7 q% C- E3 _2 ~3 i  x% {

3 `- Y% @/ B/ t7 E单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
: P0 U# @, H$ X# J. {单例模式的要求
3 \) T  N, Y' O/ U! s& d/ d) H2 f6 G- A) O) Q
构造方法必须私有化(确保只有自己能创建)" {5 j, s7 j1 v. l
以静态方法返回实例(外界不能通过new来获取到对象)
4 D2 X+ O+ [1 R' j2 o& d确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)  n; }6 H2 G' N. P+ i5 @/ G
单例模式的实现
# N, J  G+ q! g- R1 [: ?+ O. E' }0 y: J- {1 \
1、懒汉式(线程不安全)7 ]# ~2 ]. t  x( M" e! l7 ~- l5 Q

3 V; H6 t5 S, L5 A& |% j' W描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作, g4 {- |, s' ]) j: ^" V7 G: W
//懒汉式(线程不安全)1 _) J7 ~2 B3 q) L
public class Singleton {  4 ]1 b* M7 ^( r0 _# R
    private static Singleton instance;  ! L. s$ [. D! H' p6 k
- G+ X2 p% [* e  n( `$ y/ ^  X0 X
    private Singleton (){}  
; i: N( X& s$ S' z0 w4 t
0 b0 w! U7 l, K3 x    public static Singleton getInstance() {  ( M+ \  r  B0 ?+ l; X$ l
        if (instance == null) {  
/ D5 z0 h6 ]0 ~            instance = new Singleton();  
" @7 b* R: p) t' [6 g; d        }  
5 M5 |9 @9 C# T9 j) v" v& @        return instance;  
# {8 q. P* e8 Z, n  K% G* k    }  
$ I1 e1 J: D4 {! S- T3 D}
! ]3 Q" A! ^' P3 A# \

2、懒汉式(线程安全)

描述:能够在多线程下正常工作,但是,效率极低

//懒汉式(线程安全)
6 |/ ?6 C% e* |2 V3 V9 W  \% |public class Singleton {  
4 Z5 G8 H5 ^  b3 M$ Z' Q    private static Singleton instance;  : k5 T" Q8 K6 I) ]2 T1 q
* j+ }$ |/ @. i8 }
    private Singleton (){}  . w- H/ c. f: p% J: F

) @' k2 R6 |" x- r    public static synchronized Singleton getInstance() {  
  g; i7 R! f/ N: ?7 e        if (instance == null) {  
3 r8 V  X+ T1 L& i8 W2 A# y            instance = new Singleton();  0 T- Y( `  v7 x1 F: ~
        }  + J  }- d3 c7 ^" o% X  ^% k% i& z
        return instance;  
/ [5 h& |- G7 d( P6 a$ V5 z+ C    }  
1 B" }2 P1 p6 V5 O3 b7 D! B3 i}
2 b' k$ B: X5 U( C$ A/ p$ \# J
" ?0 A- }+ D  y

3、双重校验锁(DCL,即double-checked locking)(线程安全)

描述:对懒汉式(线程安全)的优化,采用双锁的机制,安全且在多线程情况下能保持高性能

! `% ~! A# S7 m$ i; x
//双重校验锁5 n9 Y  ~/ e9 w9 L# w  C. X
public class Singleton {- G% |; I5 I$ q+ b8 H3 m, O
    private volatile static Singleton instance;% r* T1 g0 G3 l2 k

5 R  Z/ ?9 v, G9 C$ }4 |2 l; U    private Singleton() {0 \; d7 {7 G% p- O% M

" |  K9 _  r/ b7 N    }8 q2 G7 M# J* Q
2 m/ D) _# B& n9 O' y  [( j$ S: t
    public static Singleton getInstance() {
: i! X6 r& b2 T  a) ~0 ^2 x        if (instance == null) {; n; U2 Z( X, `  M) [- K( T8 _
            synchronized (Singleton.class) {3 u$ q: X: n6 I6 K9 J
                if (instance == null) {
7 m! a! z& m% g" M) V0 ^/ o                    instance = new Singleton();: ]* A: x2 t: g- N: S: C* N: ?6 m
                }
7 `+ B( ~) J( w' G1 |  D            }
% u3 z6 l% x7 J, j- U        }6 l' F/ J4 A# `& w. d5 m7 G
        return instance;9 t1 E5 I# m+ [8 @/ @" ^, R
    }
3 s8 U( a* M1 w' L$ s) P3 ^& h}
8 q3 Z! C& C( W5 s, U' }( e5 X% F& Y: ]% l
7 L* n3 j% Z+ Y2 G0 K

4、饿汉式(线程安全)

描述:这种方式比较常用,但容易产生垃圾对象


; ^' c8 y, J6 B/ [. F//饿汉式
: @5 u6 Y% R8 K0 H) ~7 g; Bpublic class Singleton {
% w8 t0 y# _: f4 D, l6 R, p    private static Singleton instance = new Singleton();# I7 i& j1 q7 _( v

# h1 T. ?1 |. ]& E% z' w" Y    private Singleton() {  V) t, J& M7 O& N+ r. @9 q1 ]1 \

. F2 e" u1 c; a4 |5 k. f    }$ O, z7 {- b. N/ C* t, D

2 U4 l6 q3 i5 _. n/ N/ g0 c( G5 k    public static Singleton getInstance() {. W( S; R: M/ z! l% G2 R8 F" n
        return instance;
# g4 ^4 U* h% }5 z) }& L" f- Y    }
2 m# F$ y! A& [/ ^5 T}8 z/ `) L9 I  M# D, ], l1 V% f3 a
2 P" v: m: x% d% Z; l
& @2 x; m) M) L. d! u7 X* H  c

5、静态内部类(线程安全)

描述:这种方式达到跟双重校验锁一样的效果,这种方式只适用于静态域的情况,双重校验锁可在实例域需要延迟初始化时使用

//静态内部类, n( s! h; |" H5 ~* F4 d/ f
public class Singleton {! d9 n& z+ N3 X% ]
    private static class SingletonHolder {
' a+ n! D- h4 D; l" j3 C4 B0 }" Y: o        private static final Singleton INSTANCE = new Singleton();
: b5 x4 y: s0 Z- s    }
8 G$ A; @4 E5 w4 s* d; `: I; H
" M; J" R0 @' ?6 ?' |    private Singleton() {2 k5 @4 `; g! ~/ z3 T4 F/ s  S

& H0 p& N' T2 {' R! H' w    }
9 k* f, R. f2 c7 F  i# Q) g1 b
, c0 b5 Q, v6 d$ \. f. b( f    public static final Singleton getInstance() {
* j( ?5 q% p, F/ a        return SingletonHolder.INSTANCE;: o- u* y: b+ Q3 j" y
    }
+ ?& ?) \' t; @0 e% `& Z) ^/ q}
' U! Q9 x4 u* v/ `" j# ?. L2 t2 V

6、枚举(线程安全)

描述:这种方式还没有被广泛采用,但是这种实现是单例模式的最佳方法。更简洁、自动支持序列化机制、绝对防止多次实例化


7 Z+ j6 a$ ~: q5 u( v//枚举
( u/ H) F7 Y( V# L% ?1 n! ypublic enum Singleton {! B0 S* e- U" `, E* C  K- u
    INSTANCE;% z* T, K6 F- I2 L# C

+ Z) m. A4 Y5 k; N/ q. S    public void whateverMethod() {4 [( {( x3 r2 B. \0 r) X0 l
2 \, z3 d+ G8 {! p
    }3 U2 T- @9 t' O  |) h' u1 O5 L8 k
}' c  g1 w$ v$ ^. H2 o" a7 y! M' l

$ I2 A& a7 ?9 w0 a1 B! a8 `
- c, s( {) U2 q" n" Y  v总结- O  ?$ o# I! T) h; V3 w" E

5 p! n7 k. F: k3 M一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。
0 }+ @+ U/ ~$ Q5 x1 z! I1 O7 {PS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~
# C, W0 w; t: ]& U# J# z6 J————————————————3 c- x: \: u) V5 q  j8 `

  U6 j0 H4 I/ U; [9 v1 }& M" H& p3 o( w6 i$ p
  O+ f! y  U+ x0 H$ i/ E

5 }& d5 l' x1 x3 G2 z. N7 G
9 b, O( D" q4 m/ h1 D! V
$ ~4 Y/ m* t* x7 m$ N- x
4 ?/ D4 ^' o* a, ~" Z2 C! a/ i9 D- |0 E5 Q* J& b

$ H0 e: h5 j4 n  }9 S- K3 s1 }4 e" r原文链接:https://blog.csdn.net/weixin_37686415/article/details/105164764
' S' n( _8 E+ l( ]& w5 x6 j+ x+ ~/ o2 d% [2 O$ _; i

/ ~2 g5 C7 {# n, u
作者: 1091597757    时间: 2020-4-1 18:08
厉害了!!!!!!!!!!$ i' i5 o$ g/ M6 I5 a" |





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5