前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >23种设计模式之——单例模式

23种设计模式之——单例模式

作者头像
良月柒
发布2019-03-19 16:02:50
2690
发布2019-03-19 16:02:50
举报

什么是单例模式?

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

什么时候用到它呢?

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。

一个最好的方法就是,让类自身负责保存它的唯一实例。

这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

单例模式有什么好处呢?

1、单例模式可以保证唯一的实例。

2、单例模式因为Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。

单例模式分为饿汉单例模式和懒汉单例模式。

饿汉单例模式:静态初始化的方式是在自己被加载时就将自己实例化,所以被形象地称之为饿汉式单例模式。

懒汉单例模式:要在第一次被引用时,才会将自己实例化,所以就被称为懒汉式单例模式。

懒汉单例模式实现:

Singleton类,定义一个GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例。

代码语言:javascript
复制
/** * 作者:LKP * 时间:2018/7/26 */public class Singleton {    private static Singleton instance;
    private Singleton(){}
    public static Singleton GetInstance(){        if(instance == null){instance = new Singleton();}
        return instance;
    }}

构造方法让其private,这就堵死了外界利用new创建其实例的可能。

GetInstance()方法是获得本类实例的唯一全局访问点。

若实例不存在,则new一个新实例,否则返回已有的实例。

客户端代码:

代码语言:javascript
复制
/** * 作者:LKP * 时间:2018/7/26 */public class Client {   public static void main(String[] args){
       Singleton s1 = Singleton.GetInstance();    
       Singleton s2 = Singleton.GetInstance();
       if(s1 == s2){
System.out.println("两个对象是相同的实例。");}}}

运行结果为:

比较两次实例化后对象的结果是实例相同。

多线程时的单例

在多线程的程序中,多个线程同时,注意是同时访问Singleton类,调用GetInstance()方法,会有可能造成创建多个实例的。

如何解决呢?

可以给进程一把锁来处理。synchronized是确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

代码实现:

代码语言:javascript
复制
/** * 作者:LKP * 时间:2018/7/26 */public class Singleton {      private static Singleton instance;
   private Singleton(){}
   public static Singleton GetInstance(){      synchronized (Singleton.class){         if(instance == null){instance = new Singleton();}}
       return instance;}}

由于有了synchronized,就保证了多线程环境下的同时访问也不会造成多个实例的生成。

每次调用GetInstance()都需要synchronized,这种做法会印象性能,所以还需要对该类进行改良。

改良之后的代码:

代码语言:javascript
复制
/** * 作者:LKP * 时间:2018/7/26 */public class Singleton {    private static Singleton instance;
    private Singleton(){}
    public static Singleton GetInstance(){        if(instance == null){            synchronized (Singleton.class){                if(instance == null){instance = new Singleton();}}}        return instance;}}

先判断实例是否存在,不存在再加锁处理。

我们在外面已经判断能力instance实例是否存在,为什么在synchronized里面还需要在做一次instance实例是否存在的判断呢?

如果有两个线程调用GetInstance()方法时,它们将都可以通过第一重instance==null的判断。

由于synchronized机制,这两个线程只有一个进入,另一个在排队等待,必须要其中一个进入并出来后,另一个才能进入。

但是此时如果没有了第二重instance是否为null的判断,则第一个线程创建了实例,而第二个线程还是可以继续再创建新的实例,这样就没有达到单例的目的。

饿汉单例模式实现:

代码语言:javascript
复制
/** * 作者:LKP * 时间:2018/7/26 */public class Singleton {    private static final Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton GetInstance(){        return instance;}}

饿汉单例模式的加载方式是在自己被加载时就将自己实例化了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的成长之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是单例模式?
  • 什么时候用到它呢?
  • 单例模式有什么好处呢?
  • 单例模式分为饿汉单例模式和懒汉单例模式。
  • 懒汉单例模式实现:
  • 多线程时的单例
  • 如何解决呢?
  • 我们在外面已经判断能力instance实例是否存在,为什么在synchronized里面还需要在做一次instance实例是否存在的判断呢?
  • 饿汉单例模式实现:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档