数学建模社区-数学中国

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

作者: 杨利霞    时间: 2020-3-30 17:20
标题: 浅谈单例模式的实现方式
浅谈单例模式的实现方式  {# k* x2 g  n7 W; R
单例模式(来自菜鸟教程)2 k$ p, E' [4 j/ x+ t0 w% S

+ ~9 G; I6 a( |7 ^单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。- [5 U. Q2 R4 E8 C
单例模式的要求
* d  R! s6 v) u9 f% i" V
! Y4 @; b7 q4 g% V  R构造方法必须私有化(确保只有自己能创建)
% O; }6 I4 \3 ~( `( g7 F% X# B1 b以静态方法返回实例(外界不能通过new来获取到对象)
9 Z4 j9 \  J7 t/ R确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)
/ _6 w- f/ @) |. P# Y+ F! t' t: n单例模式的实现
2 Q6 s" X4 \7 }) \& `/ U9 h+ w9 _
1、懒汉式(线程不安全)
, e& n) l- K! f7 J: Q- L9 d$ P6 ^# d# W4 T6 j8 ~4 w4 d
描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作' {; g' n7 J% o# `4 U" |
//懒汉式(线程不安全)  z# k! ^5 n8 M' Z& Z
public class Singleton {  
2 D0 T5 \& w& z+ s/ J7 U1 z    private static Singleton instance;  9 y' D6 |% a6 F' t

0 k' c+ N! I  I5 T& b    private Singleton (){}  % s0 B0 e- w: t9 Q  v' l6 I  e

$ ~# _9 |* N6 i7 _! {3 \# `    public static Singleton getInstance() {  ! M* n" ^- D, C$ ~$ P$ s. X
        if (instance == null) {  
! l. z- x" `+ U            instance = new Singleton();  
/ w4 i' X4 {+ _6 \8 }. g        }  
" i. ~. e! s2 _- i; ~" Q1 I        return instance;  
( I- a$ g% s, h% e3 I. Q' S! h3 u    }  3 p) r3 @+ X( ?" N* h$ @
}/ {9 c- \  V' O' t2 z  W

2、懒汉式(线程安全)

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

//懒汉式(线程安全)* j5 _0 ?) F* R5 f
public class Singleton {  
1 ?8 y/ @0 w( z- q+ d    private static Singleton instance;    B$ t; l6 \  a& b
/ V3 \) _7 q6 U# I9 Q1 ?& q0 `
    private Singleton (){}  
" D3 t) Q) q, E$ V9 ^# n- O
6 B" ~# S! K/ c8 S( Q1 a    public static synchronized Singleton getInstance() {  
+ R1 U6 i6 }5 m$ g. w        if (instance == null) {    q" K2 K! @9 C! X. T
            instance = new Singleton();  5 Y  O# b" I4 w2 o8 N
        }  
2 n5 b6 n& q6 A" B- \# o        return instance;  
% {! @% E% k2 H( k1 G    }  
+ H0 V5 E6 e( s8 Y1 Q4 f" r}
9 P) d/ W0 _' i/ h! P' i% C0 U7 Q& c' t$ h, i, o# w

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

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


6 G8 e. B. b+ b% l0 n% P" }//双重校验锁
1 L( ^, k+ z% tpublic class Singleton {- W' K! ?) d# ?. u5 ?
    private volatile static Singleton instance;/ B$ T+ m' o* Y& R* ?- }+ M

/ k% R# [) _1 j2 g    private Singleton() {
$ L' J  ]; e9 P  {2 {; \& C2 ~% u/ W5 [3 T+ S, Q/ n
    }
9 R* A; T9 I8 j8 X2 e
1 F& @' X2 r% K, h% D    public static Singleton getInstance() {5 w  s* u, H: R; |
        if (instance == null) {. P5 r, h6 X% z" s5 F
            synchronized (Singleton.class) {! i' E$ g& X' B3 G3 q
                if (instance == null) {
( ]2 Q  w! T* a4 u                    instance = new Singleton();+ f" m2 v  B2 @) @* ?! d) A
                }
6 O7 K5 }) g% J+ q; @            }7 u" H9 c- N: t
        }
, g; z2 u/ v3 p* z        return instance;( F- e& R6 [* O0 J0 N% {" w; k
    }
/ _6 ^) m7 Z3 X8 C}1 E+ v( `" f8 I/ b

; Y1 z! H5 p9 \# T) d6 S& \- K# v; q7 V5 [

4、饿汉式(线程安全)

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


$ o: v& q" \) Z' p* o" l. r//饿汉式
, S3 }# }7 c6 T" wpublic class Singleton {/ T- K& H/ Q, `7 C
    private static Singleton instance = new Singleton();# i, g/ A; l5 ^0 t% f& C

7 s% S) a* z* v7 m2 `2 v    private Singleton() {
! u9 G( d* L* g5 \$ J1 X: X% k3 Y( d! i. k, {
    }
7 V' I4 h; a) c7 H2 o* G+ E1 V7 I+ K; P$ r8 A. c5 ~+ y
    public static Singleton getInstance() {
2 _3 F9 J" O0 I        return instance;8 x5 @2 n9 `7 r" ?/ j' O* l
    }
7 b/ X, i% ^' e}4 W2 E( o" o: T! V! z1 y% A* g( y

/ b3 _8 T" q5 K( ^: @' j! a
& Z1 Z6 V4 G7 [% s# r' y- L, g0 O

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

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

//静态内部类; R! N; Y9 e0 J* s' X
public class Singleton {8 p7 R9 r. A5 Y) P. Z& P
    private static class SingletonHolder {9 Y3 |' |) ^, L, K/ U6 q! n
        private static final Singleton INSTANCE = new Singleton();
* R' }/ F' |/ m    }
% \; p1 W/ |  ]: J
6 e. i9 b3 X; e$ O( H( x' }- M8 P    private Singleton() {2 P1 ?: k- \' ^- W& H
- i4 w; ]; X7 y  C# L
    }* f$ n' G5 U5 G/ j% P* p2 s9 T
2 X: B. W2 d9 `3 V- K4 {
    public static final Singleton getInstance() {
* `: P7 [: N1 O- `; M        return SingletonHolder.INSTANCE;$ Z" P; u" ^5 e4 n% L; }
    }
& [1 z5 E  |6 n7 J3 w}& h7 k1 h5 m1 ~3 ]+ a
" s  r5 J% |6 M( ?" ]5 s

6、枚举(线程安全)

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

3 `* W( p' B, z0 ], V
//枚举5 t1 y( s$ s% T% M  t; o
public enum Singleton {4 t( j5 `1 B7 f# |
    INSTANCE;( z! y, g5 s# P7 Q% \8 z. @7 E

4 ], }, L4 h* D; c- B) K    public void whateverMethod() {1 V  O( o' F! T
3 o$ |* K4 n! k1 {
    }
! S: _0 m7 u9 A- l. O9 B1 p}! j$ f, {2 u9 j7 o" l

3 T% g( b$ g' f2 g$ d$ l4 b" [  ?+ S9 P5 K6 v' O$ W4 j
总结
$ F# B4 N% ^, N! G7 n( R) e0 k# w8 d% o5 D
一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。
2 E! r) N# P+ J+ XPS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~
4 t% J& X7 q" [/ E( w0 d————————————————1 ~' A1 Z9 n1 q! M2 n! \! H
9 v' k1 e5 S6 [" N' M- ~

$ H1 ]9 B; w" [
# `5 Y9 t% e; b& A7 H
( C4 B/ H1 l' s6 a% I/ M& k+ s7 _) O2 G; j, p+ d
7 z7 u/ g$ C2 f/ O% P4 \

7 Y* `1 @2 `! @# t" P$ ^& u8 F. h" ?& X

6 p- Q0 Q, l0 E& d% J原文链接:https://blog.csdn.net/weixin_37686415/article/details/105164764( O/ E. }7 U- V$ y

* l9 h* u+ ~5 {5 `# J# h. N( G! w' `# c: v/ Q. M" h9 \' t9 c, H

作者: 1091597757    时间: 2020-4-1 18:08
厉害了!!!!!!!!!!$ O+ i+ a6 n1 U  h+ n, y; C





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