JAVA单例设计模式简析

来源:互联网 发布:淘宝客联盟如意投 编辑:程序博客网 时间:2024/06/08 11:40

一.设计模式是什么?

设计模式的概念起源于建筑行业,其实生活中的方方面面都有其模式,从衣食到住行,用最近比较流行的话来说就是套路。软件开发设计模式的概念简单说就是前人总结的经验,运用这些经验针对某一问题研究出的行之有效的解决方案。在现在公司的开发中最为常见,例如:java ee中的框架就可以说是设计模式的一种体现。

        java的设计模式有23种,也就是我们常说的GOF 23,在这里就不再一一细说,有兴趣的朋友可以百度,在网上搜索一些资料。

二.什么是单例设计模式?

既然我们说设计模式是为了解决某一既定问题,那么单例设计模式也是为了解决某一问题而产生的。在日常开发中,我们难免会碰到这样的需求,那就是一个类中在内存中只存在一个对象。这种设计也许乍一听会让人有不知其所云的感觉,但是在实际开发中的应用确实很常见的。例如:

      1.一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务

      2.一个系统只能有一个窗口管理器或文件系统

      3.一个系统只能有一个计时工具或ID(序号)生成器

     具体说来,比如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。

    解决该问题可以这样理解:

    1.为了必先其他程序过多建立该类对象,先禁止其他程序建立该类对象

    2.为了让其他程序可以访问到此对象,只好在本类中自定义一个对象

    3.为了方便其他程序方便访问该对象,可以提供一些访问方式

    单例模式的特性有三个:

    1.某个类只能有一个实例;

    2.它必须自行创建这个实例;

    3.它必须自行向整个系统提供这个实例

    其具体实现方式也可以细分为三个步骤:

    1.将构造函数私有化

    2.在类中创建一个本类对象

    3.提供一个方法可以获取到该对象

三.单例设计模式的优缺点:

优点

一、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
二、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。

缺点

一、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
二、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
三、对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。。

四.具体代码:

一种形式:饿汉模式

Single类一进入内存,对象就已经建立

public class Single{

private Single(){}

private static Singleinstance = new Single();

public static Single  getInstance(){

returninstance;

}

public static void main(String args){

Singleinstance = Single.getINstance();

}

}

 第二种形式:懒汉模式

       对象是方法被调用时才开始初始化,对象延时加载。

Single类进内存,对象还没有被加载,当调用getInstance()方法才建立对象。

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

第三种形式: 双重锁的形式


public class Single{
    private static  Single instance=null;
    private Single(){
        //do something
    }
    public static  Single getInstance(){
        if(instance==null){
            synchronized(Single.class){
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
     }
}
懒汉模式既然是延迟加载,必然会有一个阻塞的过程,那么就容易出现多线程并发的问题,一般我们会加个synchronized锁住getInstance(),防止线程并发。但如若按照第二种形式的懒汉模式将整个getInstance()锁住,难免会降低效率,所以双重锁形式严格说来,其实是懒汉模式的一种衍生模式。在getInstance()方法内部添加同步锁,防止线程并发的同时,又能相对于懒汉模式,效率得到提高。

  注:

面试中懒汉模式被提及的概率要更大一些,因为即涉及到设计模式,又与线程安全问题相关。但在实际开发中饿汉模式被应用的居多,因为饿汉模式结构更为简单,直接返回一个对象,出错的概率自然会更小,且应用也更为方便。

(文本内容部分来源于百度与毕向东老师的教学视频)