重新认识单例模式

    读到《Head First》单例模式这章的时候我本来是想跳过这章的,因为我一直觉得单例模式实在太简单了,即使在我系统的学习设计模式之前,我也可以分分钟写出一个单例模式的例子,(以下程序使用Java语言实现)就像下面:

public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance(){
        if (instance==null)
            instance = new Singleton();
        return instance;
    }
}

因为这个实在太经典了,但是本着再看下,只当复习的态度,就看了一下书上写的,才发觉自己又漏掉了一些概念,所以认识的不够完全,为什么用“又”,因为之前自己已经犯过这样的毛病了,看来以后学习还是不要太浮躁,即使是觉得已经了解的内容,也应该再看一下,没准不同的书,不同的人他写的东西有可能都有新的知识在里面呢,这也许就是温故知新的道理吧。比方说这里我就漏掉了一种情况,那就是在多线程中。没错,如果只是写单线程程序,那上面这个例子就完全够用了,但是如果牵扯到多线程,就不得不考虑线程安全的问题,假如你有两个线程,第一个线程执行到判断instance是null 然后接着cpu它切换到第二个线程也执行到判断instance是null,那么好,这样一来岂不是就创建了两个对象?那还怎么能称作是单例模式呢,这个对象就不唯一了,所以要加锁来解决。

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

可是加锁会影响效率,如果你的这个单例对象需要频繁的使用,而你的程序又很重视效率,那怎么办呢?那就可以这样:

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}

除此之外还可以有一种方式,那就是用“双重检查加锁”

public class Singleton {
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}
最后说些题外话,其实设计模式学了也不能乱用,而且设计模式只是大的模式,具体到实现也会有细微的变化,具体怎么做,还是要结合实际情况,书上也强调不能滥用设计模式。除此之外,就是学习的过程中一定要明白它到底好在哪里,多想想为什么,就拿单例模式来说,如果我只是因为有一份数据是全局唯一的,又想再程序的任何地方方便的使用它,那为什么不考虑用全局变量的方式,比方说定一个静态变量来存储?因为静态变量一开始就要初始化如果你的对象十分庞大会耗费内存资源,而程序一开始其实是用不到它的,会造成资源的浪费。所以有时候多想想为什么要这么实现,有利于加深自己的印象和理解。

 

fantasycoding.net 2016-2024 © All rights Reserved京ICP备2020039454号-1