疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java基础单例模式介绍


 

 
 
一、概念
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。就笔者认为,单例就是不让外界创建对象。
 
1.1概念剖析
 
对于单例的话,从上面的概念剖析,应该满足下面的几个条件:
 
第一:单例类中只能有一个单例对象;
 
第二:单例类必须自己创建自己的唯一实例对象;
 
第三:这个实例对象能够给外界访问到,并且外界不能够自己创建对象。
 
二、常见几种单例模式的方式
在java中,对于单例模式一般来说,分为懒汉式,饿汉式,以及登记式,但是登记式一般较少看到,所以也容易忽略。笔者若非今天突然想总结一下,在网上查找资料,也不会注意到这个。下面按照这种方式来贴出代码,并进行解释。
 
2.1饿汉式单例类
 
复制代码
package com.ygh.singleton;
/**
 * 饿汉式单例类
 * @author 夜孤寒
 * @version 1.1.1
 */
public class HungerSingleton {
    //将构造方法私有,外界类不能使用构造方法new对象
    private HungerSingleton(){}
    //创建一个对象
    private static final HungerSingleton hungerSinleton=new HungerSingleton();
    //设置实例获取方法,返回实例给调用者
    public static HungerSingleton getInstance(){
        return hungerSinleton;
    }
}
复制代码
写一个测试类,测试是不是实现单例:
 
复制代码
package com.ygh.singleton;
/**
 * 测试单例类
 * 
 * @author 夜孤寒
 * @version 1.1.1
 */
public class Test {
    public static void main(String[] args) {
        /*
         * 构造方法私有化,不能够使用下面方式new对象
         */
        //HungerSingleton hungerSingleton=new HungerSingleton();
        //使用实例获取方法来获取对象
        HungerSingleton h1=HungerSingleton.getInstance();
        HungerSingleton h2=HungerSingleton.getInstance();
        System.out.println(h1==h2);//true
    }
}
复制代码
从上面可以看出:这个测试类的两个引用是相等的,也就是说两个引用指向的是同一个对象,而这也正好符合单例模式标准。到这里,饿汉式介绍结束。
 
2.2懒汉式单例类
 
复制代码
package com.ygh.singleton;
/**
 * 懒汉式单例类
 * @author 夜孤寒
 * @version 1.1.1
 */
public class LazySingleton {
    //将构造方法私有,外界类不能使用构造方法new对象
    private LazySingleton(){}
    //创建一个对象,不为final
    private static LazySingleton lazySingleton=null;
    //设置实例获取方法,返回实例给调用者
    public static LazySingleton getInstance(){
        //当单例对象不存在,创建
        if(lazySingleton==null){
            lazySingleton=new LazySingleton();
        }
        //返回
        return lazySingleton;
    }
}
复制代码
测试类:
 
复制代码
package com.ygh.singleton;
/**
 * 测试单例类
 * 
 * @author 夜孤寒
 * @version 1.1.1
 */
public class Test {
    public static void main(String[] args) {
        /*
         * 构造方法私有化,不能够使用下面方式new对象
         */
        //LazySingleton lazySingleton=new LazySingleton();
        //使用实例获取方法来获取对象
        LazySingleton l1=LazySingleton.getInstance();
        LazySingleton l2=LazySingleton.getInstance();
        System.out.println(l1==l2);//true
    }
}
复制代码
从上面可以看出:这个测试类的两个引用是相等的,也就是说两个引用指向的是同一个对象,而这也正好符合单例模式标准。到这里,懒汉式介绍结束。
 
2.3懒汉式和饿汉式的区别
 
懒汉式是当没有对象的时候,就会创建一个单例对象,当有对象的时候,就不会再创建对象,这个说起来可能不是那么容易理解,但是读者如果有兴趣了解更深,可以在eclipse中使用断点来测试,将LazySingleton类的if花括号内的内容加上断点,然后在Test类中,使用debug运行,这样子就能够很容易体现出来,第一次创建了一个对象,但是第二次没有创建对象。
 
饿汉式则是实现就用final这个关键字将对象创建好了,当调用者需要实例对象的时候,就可以通过getInstance这个方法获取创建好的实例。
 
2.4登记式单例类
 
对于登记式单例类,笔者也不是很熟悉,贴了一段网络上的代码以供自己学习参考,请读者自行学习。
 
复制代码
import java.util.HashMap;
import java.util.Map;
 
/**
 * 登记式单例类
 * @author Administrator
 *
 */
public class RegisterSingleton {
    private static Map<String, RegisterSingleton> map = new HashMap<String, RegisterSingleton>();
    static {
        RegisterSingleton single = new RegisterSingleton();
        map.put(single.getClass().getName(), single);
    }
 
    /*
     * 保护的默认构造方法
     */
    protected RegisterSingleton() {
    }
 
    /*
     * 静态工厂方法,返还此类惟一的实例
     */
    public static RegisterSingleton getInstance(String name) {
        if (name == null) {
            name = RegisterSingleton.class.getName();
            System.out.println("name == null" + "--->name=" + name);
        }
        if (map.get(name) == null) {
            try {
                map.put(name, (RegisterSingleton) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
 
    /*
     * 一个示意性的商业方法
     */
    public String about() {
        return "Hello, I am RegSingleton.";
    }
 
    public static void main(String[] args) {
        RegisterSingleton single3 = RegisterSingleton.getInstance(null);
        System.out.println(single3.about());
    }
}
复制代码