数学建模社区-数学中国

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

作者: 杨利霞    时间: 2020-3-30 17:20
标题: 浅谈单例模式的实现方式
浅谈单例模式的实现方式" `( e  F1 h1 D' U/ X( i* {
单例模式(来自菜鸟教程)
2 }5 U9 h/ T8 G; A
5 M" g4 t% {1 E单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
+ B! _) n) d2 t. Q( |单例模式的要求
1 M* _% @1 W7 `1 v1 E) z: @
/ J6 X% g8 t. m% a构造方法必须私有化(确保只有自己能创建), x3 K( r- ~/ j& v0 `+ v
以静态方法返回实例(外界不能通过new来获取到对象). @! q9 a. ~* {. I) p
确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)
6 x' z2 |1 Q) V; x: h( x单例模式的实现
, X( E3 p: `# {/ n. [6 L/ X" i5 F. `5 \: u
1、懒汉式(线程不安全)1 w" Z8 {1 c+ C4 Q: n
5 ?9 p7 G/ a+ e, P
描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作7 S" r1 r3 V0 B3 J" V" Y' s
//懒汉式(线程不安全)6 q! }8 |' I9 j
public class Singleton {  , D$ R7 Y2 L& ?$ ^" L' n8 j  I6 [4 M
    private static Singleton instance;  
7 [7 v. l* J7 p
$ m1 G& k8 }' f$ v1 k8 ]2 Y    private Singleton (){}  - L0 x- r- @4 }8 J

6 ?! B  m5 q$ S8 N7 D0 K5 g( ?3 D    public static Singleton getInstance() {  . q6 i  ?  L& k; ?, R
        if (instance == null) {  3 V  H9 a/ p; {( x& P' h
            instance = new Singleton();  9 a6 ?2 O9 X/ O8 C' u/ s
        }  " `9 Q$ m* e, z/ K) G/ v5 u
        return instance;  & ?) S# v# S; E' r
    }  5 O% k) t, M8 R! m
}
" c* {- ]3 W9 w% p+ ^

2、懒汉式(线程安全)

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

//懒汉式(线程安全)7 w3 @2 ?+ |: K0 O: V, b
public class Singleton {  . F6 f. ~- Q8 K1 B
    private static Singleton instance;  # d% W( ?0 _( f& W2 u0 J) ~9 ]
) L. D' v9 O- n2 f5 q' {
    private Singleton (){}  
6 s) u5 D( y5 z" ~4 ?4 k5 e$ I' M& l, Z
    public static synchronized Singleton getInstance() {  ) Y; j2 Z' p2 y/ n( t
        if (instance == null) {  
. t5 s0 ]! o4 D' h            instance = new Singleton();  . S- I5 n+ s: X; G% ?
        }  
  T7 ^! Z& k5 M, p        return instance;    n! F2 h; X; @1 X
    }  
& {5 [) ~( c* ^}
  A" t# F3 o+ i6 M( m8 k, f4 }+ m
7 h3 V9 `! a" U4 {$ N" u5 g

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

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

, P' ]: g) D4 }0 ]% R3 f# a
//双重校验锁
, X* V( O/ }  v) Fpublic class Singleton {
9 ^( B) O, W1 H1 H    private volatile static Singleton instance;
: F* [- d/ o( b' c9 ?& e; E  _8 g8 j9 `; ], K$ @. E
    private Singleton() {# ^: S& U# w; ~; D. c

* g: F1 @& z* n( ]    }
! j$ e$ s$ D3 J  B" f8 B/ W6 Q! h+ c+ ~, _
    public static Singleton getInstance() {- z* j5 A  W9 M: G* o1 p
        if (instance == null) {( @3 _% L8 S6 B
            synchronized (Singleton.class) {
0 _7 W4 H! f  N! `  P                if (instance == null) {
* ^% f2 J, h. ]" w3 f- p                    instance = new Singleton();1 M  M$ q+ M8 `- C
                }$ L- s% S% k7 D% F
            }! L4 L. ?2 y' t5 N4 [) {
        }) G! w, ?/ _5 j* k0 ^; X$ D
        return instance;
$ S- L' f  C, I1 b- A    }- s7 |0 h4 I. H2 C
}
  d! |; E/ z) ~' J2 g3 }8 g5 F5 b+ x) u4 K0 {
$ s6 }6 Y9 t) k, s

4、饿汉式(线程安全)

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


: j) ]* z8 T# y, ~& ?3 n/ S6 r" Y//饿汉式) P2 `# x' x& v9 f& E
public class Singleton {
" f8 V# E: _$ U. X' K' a    private static Singleton instance = new Singleton();
- q! @  V" A( m, G* Q8 d: B# b% m) `
/ o, W! {0 k1 c% S; r    private Singleton() {. j- c, z2 [! S9 @
1 d& w0 C8 T# G0 S
    }
9 r, [6 I- r0 T, {7 A! Q7 f* y% G$ U
: L. {" h6 y8 I. d$ o. g9 [    public static Singleton getInstance() {
, k9 i- V! Y! b* z& s  l% W# T        return instance;* N* [8 i* V& v6 B$ P) K: S
    }
- @1 @& I4 r* m( v+ J}, L" a- g: u, a: M
3 W, y  t, u* J% y
* q! K- j) x: F

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

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

//静态内部类
: m/ x( b5 M4 M! Q- J# H, \public class Singleton {% P" b7 g0 h# k1 v: h$ [; @
    private static class SingletonHolder {
6 w$ w" J& J# x( y# @. G& X! Z% ?        private static final Singleton INSTANCE = new Singleton();
, N' @3 t' v: ~    }
+ d% e4 z" k, ]  j* p+ a6 s
$ R( F; W8 o( T. {0 s7 z% r% w7 V    private Singleton() {
4 s) x. u5 U7 t3 R3 ~5 E
  J( H3 s0 c! V- k% a    }( V' y' N% V$ e+ \7 m

' y; q3 |$ e: e) k) r7 O  }    public static final Singleton getInstance() {
+ \3 H* g% l  H( F6 s        return SingletonHolder.INSTANCE;
/ L: E# L% x; E% ~  ?5 ?    }- c/ [: |3 C. m' S$ E7 m2 u
}
. M$ t' Y3 a- [
3 y2 {0 r6 u5 U# D

6、枚举(线程安全)

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

" e. [$ M, {  h, U. z
//枚举( w, Q  `4 J, G( u) S/ c
public enum Singleton {
9 ]7 c3 J  }2 e# f  l    INSTANCE;
% `& h. [; O& K9 Z
; j) q; X8 }- y6 U    public void whateverMethod() {' w* f! }7 b! h

4 q/ W) p& b0 P7 ]7 W( R$ T( p    }. ]( d' ]" K* M# B
}
, ^* \7 k6 k  q. _8 j/ F4 `3 L2 D) v

+ X/ W! c; Q$ S1 o总结; s( u( j: E$ t& b
4 u/ l0 M  ?1 m0 u* B5 B; i1 K' O
一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。
" e" F6 C' b6 x# ^) L1 XPS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~) T6 K% v% W0 H& J
————————————————( t0 v& m6 ^# m' P* X& t; C
1 E0 f0 a2 b5 ]3 _7 D0 L5 n

* Q- i3 N) r; _: o. g- R3 V2 ^* P9 W# k
; v2 Q6 R7 k' u1 l# A
; Q$ V" o5 p: k6 ^1 W# M
0 V8 C! U$ O# b- S
; N% Z' @0 T9 W0 G+ X4 ^- q
! M$ w1 ~2 H  v. i  q9 t+ F' c

: l% D4 A" [3 |# M# l) `原文链接:https://blog.csdn.net/weixin_37686415/article/details/105164764
1 s; d% o* E3 H9 U
/ g% c! _9 Y* k0 W2 u' v0 u7 t  v- C% W& L5 z# _& ~

作者: 1091597757    时间: 2020-4-1 18:08
厉害了!!!!!!!!!!
% r/ f% E4 X% Q* A/ n




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