您的位置:首页 > 其它

设计模式系列1---独当一面的单例

2015-12-30 00:24 176 查看
在开始写之前我想吐槽下CSDN!

源码探索系列6和14居然不见了,上次找版主去找回一次别的文章!这次居然跑了两篇,服务器要高可用啊!

现在还记得14写的内容是HandleThread,但第六篇那么久那里还记得写的是哪篇,想补都补不回来了!

我很怀疑这CSDN的人自己都不用这个来写文章的,写文章过程遇到一堆bug也没改进下!

整个CSDN的博客产品线一点真的都不用户友好,设计逻辑上一堆乱起八糟的!

怪不得没落成这样,还是有点原因的。

为了写这篇文章,内心压制了好久,那些文章都是我每天下完班辛辛苦苦熬到凌晨一两点才写完的!

翻看了那么多代码,熬了这么久!真的内心难以忍受这样的错误!

我要寻找一个替代CSDN来写文章的地方!

以前自己搭博客写,但传图片太麻烦了,现在很多网站都限制外链的。哎!

一个可以让人舒服写字的地方真不容易找!

好了,我大骂完了,并且也不打算删除这些负面文字

起航

我们的单例模式在我们开发安卓的过程多多少少会遇到,或者我们在写的过程就可能写过了。

他的最原始的样子像下面这样:

public class MySingleWork {

private static MySingleWork mySingleWork;

MySingleWork() {
}

public static MySingleWork getInstance() {
if (mySingleWork == null) {
mySingleWork = new MySingleWork();
}
return mySingleWork;
}
}


看上面的例子,我们可以看到一个基本的模型:

一个静态的实例变量

一个私有的构造函数

一个获取这个静态实例的静态函数

这个就是单例的基本套路,他起源于对资源的控制上要求有且只有一人,真像我们以前的皇帝一样,一个国家只能有一个皇帝,如果有两个,变成双重心,那可是要出问题的啊。就像你有两个脑袋,一个说要前进,一个说要后退,你说该怎么办呢?所以最好只有一个负责人。因此我们需要一个独当一面的东西出来。

这个就是单例(
Singleton


但上面的单例是有点小问题的,不过如果不涉及多线程,多进程的话,那就没什么问题。

所有的问题基本是确保是否唯一效率的问题!

上面的单例模式的问题就是可能会导致不惟一,当有多个线程并发的调用
MySingleWork.getInstance()
的时候,就有可能闹问题啦!

维持我们加了一个同步锁
synchronized
,这个加锁也挺有学问的,加的方式也挺多的,下面列几个曾经看到的。

版本:

public synchronized static MySingleWork getInstance() {
if (mySingleWork == null) {
mySingleWork = new MySingleWork();
}
return mySingleWork;
}


版本2:

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


版本3:

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


这三个版本,显然是第三个最好,因为其实我们大部分的情况是实例化了,再继续调用的情况。即多次的调用,这时候如果还有
synchronized
要面对,效率就降下来了。虽然第三版的第一次效率低,不过后面就没有影响了,是笔合理的代价,而且在很多高并发情况,这个也是不会有错误的,除了多进程的情况。

不过这个模式还是存在失效的情况,到底怎么个失效法呢,欢迎看下这里,清英大神的并发编程网里面的一篇完美的单例实现(The Perfect Singleton)对这个问题的讨论,这里复制下解决方案,静态内部类单例模式

public class MySingleWork {

private MySingleWork() { }

public synchronized static MySingleWork getInstance() {
return SingletonHolder.mySingleWork;
}

private static class SingletonHolder {
private static MySingleWork mySingleWork = new MySingleWork();
}
}


可以看到,这里由一个静态的内部类来持有,可以满足线程安全,而且知道我们调用getInstance的时候。才会去生成,即延迟加载。

除了以上,还有遇到过一种容器单例模式,这个在我们的源码探索系列里面有提到过。

public class ContainerSingleton {

private static Map<String, Object> singletonList = new HashMap<>();

private ContainerSingleton() {
}

public static Object getInstance(String key) {
return singletonList.get(key);
}

public static void registerInstance(String key, Object singletonObject) {
if (!singletonList.containsKey(key)) {
singletonList.put(key, singletonObject);
}
}
}


通过这个方式,我们把单例根据key-value对来保存,然后后面需要的就在获取。

这种看起来不是很想前几个常见的模式。

但有一点不变,某东西只有一个,不会重复的原则!

后记

本来还想继续补充点内容,但今天的心情真的一般般,特别是看到我的文章少了,下次有空再继续补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息