Re:设计单例singleton

一,什么是单例模式

  单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。

 

二,单例模式有什么用

  • 1、要求生产唯一序列号。
  • 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

 

三,如何设计单例模式

  分析:

  1,某个类只能有一个实例——构造器私有化

  2,它必须自行创建这个类——含有一个该类的静态变量来保存这个唯一的实例

  3,它必须自行向整个系统提供这个类——(1)直接暴露,(2)用静态的get方法获取

  

  创建:

  饿汉式:直接创建对象,不存在线程安全问题

  1,直接实例化(简洁直观)

  

/**
 * 在类初始化时直接创建实例对象,不管是否需要这个对象都会创建
 *
 * (1)构造函数私有化
 * (2)自行创建并用静态变量保存
 * (3)向外提供这个实例
 * (4)强调这是一个实例,用final修饰
 */
public class Singleton1 {

    private final static Singleton1 INSTANCE = new Singleton1();
    private Singleton1(){
    }

}

 

  2,枚举式(最简洁)

  

/**
 * 枚举类型表示该类型的对象是有限的几个
 * 限定为一个,就成了单例
 */
public enum Singleton2 {
    INSTANCE
}

 

  3,静态代码块(适合复杂实例化)

public class Singleton3 {

    private final static Singleton3 INSTANCE ;
    static {
        INSTANCE = new Singleton3();
        //再此可以读取一些初始化数据,外部文件,配置文件等
        //Properties property = new Properties();
    }

    private Singleton3(){
    }

}

 

 

  懒汉式:延迟创建对象

  1,线程不安全(适用于单线程)

**
 * 延迟创建实例对象
 * (1)构造函数私有化
 * (2)用一个静态变量保存这个唯一的实例
 * (3)提供一个静态方法,获取这个实例对象
 */

public class Singleton4 {

    private static Singleton4 INSTANCE ;

    private Singleton4(){
    }

    public static Singleton4 getInstance() throws InterruptedException {
        //如果实例变量为空,就创建一个实例,否则直接返回这个实例
        if (INSTANCE == null){
            Thread.sleep(2000);
            INSTANCE = new Singleton4();
        }
        return INSTANCE;
    }

}

 

  2,线程安全(适用于多线程)

/**
 * 延迟创建实例对象
 * (1)构造函数私有化
 * (2)用一个静态变量保存这个唯一的实例
 * (3)提供一个静态方法,获取这个实例对象
 */

public class Singleton5 {

    private static Singleton5 INSTANCE ;

    private Singleton5(){
    }

    public static Singleton5 getInstance() throws InterruptedException {
        if (INSTANCE == null) {
            synchronized (Singleton5.class) {
                //如果实例变量为空,就创建一个实例,否则直接返回这个实例
                if (INSTANCE == null) {
                    Thread.sleep(2000);
                    INSTANCE = new Singleton5();
                }
            }
        }
        return INSTANCE;
    }

}

 

  3,静态内部类(适用于多线程)

/**
 * 在内部类被加载和初始化时,才创建INSTANCE实例对象
 * 静态内部类不会自随着外部类的加载和初始化而初始化,它是要单独加载和初始化的,是线程安全的
 */
public class Singleton6 {



    private Singleton6(){
    }

    private static class Inner {
        private final static Singleton6 INSTANCE = new Singleton6() ;
    }

    public static Singleton6 getInstance(){
        return Inner.INSTANCE;
    }
}

 

posted @ 2019-08-07 12:42  Noperx  阅读(165)  评论(0编辑  收藏  举报