(Kotlin and Java)设计模式-单例模式

以最简单的module学习设计模式,理解最重要

设计模式持续更新中:https://www.jianshu.com/p/e3c25095c31f
连着更了几天,今天写个简单的,单例模式

前言

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

正文:

:由于单例模式是经常用到的,这里就不提供demo了(懒。。。)
本文就总结了Java中单例模式的几种实现方式,并比较了它们的优缺点

1. 最简单的实现---饿汉式

Java

/**
 * 饿汉式
 */
public class Single {
    private static Single single = new Single();

    private Single() {
    }

    public static Single getInstance() {
        return single;
    }
}

写一个单例(不管什么形式),主要注意点如下几点(该种方式不存在线程安全的问题,其是线程安全的)

    1. 成员变量 single 要声明成静态的(static),因为需要在静态方法getInstance()中访问;
    1. 构造方法要声明成私有,不然如何保证单例;
    1. getInstance()要声明成 public static的。

Kotlin

/**
 * 饿汉式
 */
object Single {
}

有童鞋要说了,这什么都没写呀。对,饿汉式在Kotlin中,只需要一个object修饰符就行了,这就是Kotlin非常厉害的地方。

2.性能优化(lazy load)——懒汉式

饿汉式的方式虽然简单,但是是基于classloader加载的,其在该类第一次加载进内存时就会初始化单例对象。这样,无论该对象是否被使用,都会创建一个single对象。

Java


/**
 * 懒汉式 --- 非线程安全
 */
public class Single {
    private static Single single;

    private Single() {
    }

    public static Single getInstance() {
        if (single == null) {
            single = new Single();
        }
        return single;
    }
}

Kotlin

/**
* 懒汉式 --- 非线程安全
*/
class Single private constructor() {
  companion object {
      /**
       * Kotlin原生写法
       */
      val INSTANCL_1 by lazy(LazyThreadSafetyMode.NONE) {
          Single()
      }
      /**
       * 翻译java的写法
       */
      private var single: Single? = null

      fun getInstance(): Single {
          if (single == null) {
              single = Single()
          }
          return single!!
      }

  }
}

Kotlin这里有两种写法,一种是纯种,一种是变种。变种大家一看就明白,就是直接把Java的方式翻译过来了。纯种的我们使用了lazy,看英文就知道是懒加载的方式,传入了一个LazyThreadSafetyMode.NONE,英文好的小伙伴一看就明白,这是线程不安全的意思。companion object的意思相当于Java中public static。

3. 懒汉式——线程安全(1)

因为懒汉式的出现,虽然解决了饿汉式的不足,但也出现了多线程的问题。于是解决懒汉式的方式就出现了,那就是我们熟知的加锁Synchronized。
Java

/**
 * 懒汉式 --- 线程安全
 * 使用synchronized保证线程安全
 * 虽然线程安全了,但因为使用synchronized关键字使加锁效率不高
 */
public class Single {
    private static Single instance;

    private Single() {
    }

    public static synchronized Single getInstance() {
        if (instance == null) {
            instance = new Single();
        }
        return instance;
    }
}

Kotlin


/**
 * 懒汉式 --- 线程安全
 * 使用synchronized保证线程安全
 * 虽然线程安全了,但因为使用synchronized关键字使加锁效率不高
 * Kotlin使用@Synchronized注解加锁
 */
class Single private constructor() {
    companion object {
        private var single: Single? = null

        @Synchronized
        fun getInstance(): Single {
            if (single == null) {
                single = Single()
            }
            return single!!
        }
    }

}

4. 懒汉式——线程安全(2):效率更高

Java

/**
 * 懒汉式 --- 线程安全 双重校验锁
 */
public class Single {
    private static Single single;

    private Single() {
    }

    public static Single getInstance() {
        if (single == null) {
            synchronized (Single.class) {
                if (single == null) {
                    single = new Single();
                }
            }
        }
        return single;
    }

}

但是上面的单例都有其缺陷:当反序列化和使用java的反射机制时,单例无法得到保证,那么,解决该问题,我们可以使用Enum(枚举)。
Kotlin

/**
 * 懒汉式 --- 线程安全 双重校验锁
 */
class Single private constructor() {

    companion object {

        /**
         * Kotlin原生写法
         */
        val INSTANCE_1 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            Single()
        }
        /**
         * 翻译java写法(变种方法)
         */
       private var single: Single? = null

        fun getInstance(): Single {
            if (single == null) {
                synchronized(Single::class.java) {
                    if (single == null) {
                        single = Single()
                    }
                }
            }
            return single!!
        }
    }

}

Kotlin原生的,我们只改变了lazy的括号的值,mode = LazyThreadSafetyMode.SYNCHRONIZED就是锁的意思,英文好的童鞋一眼就明白了。

5. 枚举实现

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化和反射机制重新创建新的对象,不过,JDK1.5中才加入enum特性, 这种方式只能在1.5之后使用。(但是Android官网不建议使用enums,占用内存多(Enums often require more than twice as much memory as static constants.))
Java

/**
 * 枚举实现
 */
public enum Single {
    INSTANCE;

    public void method() {
    }
}

Kotlin

/**
 * 枚举实现
 */
public enum Single {
    INSTANCE;

    public void method() {
    }
}

6.内部类式

虽然不怎么被大家使用,但是觉得还是比较好。还是要说一下的
Java

/**
 * 内部类实现
 */
public class Single {
    private Single() {
    }

    private static class Hodler {
        private static Single single = new Single();
    }

    public static Single getInstance() {
        return Hodler.single;
    }
}

内部类Holder,里面有外部的实例。很多童鞋可能要问,这怎么就满足懒汉式和线程安全呢?当我们应用初始化时,getInstance没有被调用,就没有实例对象,那就满足了懒汉式。当我们调用getInstance的时候,Java虚拟机为了保证类加载的安全性,所以这里就保证了线程安全。这种写法是不是惊呆了?那Kotlin又是怎么样写的呢?

/**
 * 内部类实现
 */
class Single private constructor() {
    companion object {
        fun getInstance(): Single {
            return Hodler.single
        }
    }

    private object Hodler {
        val single = Single()
    }
}

很简单,内部用object创建一个内部Holder单例,外部一个getInstance来获取的方法。也相当于是Java翻译过来的方式。


如果你对此感兴趣,可订阅(感谢你的关注):


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容

  • 单例模式 介绍 为了节约系统资源,有时需要确保系统中某个类只有唯一一个实例,当这个唯一实例创建成功之后,我们无法再...
    666真666阅读 343评论 0 6
  • 单例模式(Singleton Pattern)是众多设计模式中较为简单的一个,同时它也是面试时经常被提及的问题,如...
    廖少少阅读 560评论 0 1
  • 目录 本文的结构如下: 什么是单例模式 为什么要用该模式 模式的结构 代码示例 优点和缺点 适用环境 模式应用 总...
    w1992wishes阅读 388评论 1 2
  • 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 单例模式的使用很广泛,比如:线程池(threa...
    richy_阅读 297评论 0 0
  • 这个中秋,有点灰色。年轻的乔任梁永远的离开了。 刚听到这个消息的时候,我是不相信的。那样一个阳光帅气的男孩子怎么就...
    李铁蛋儿阅读 918评论 23 9