Water2Wine

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

单例模式

一、概念

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类智能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。

因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法智能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。

二、创建与代码实例

1. 饿汉式实现

私有化类的构造器->内部创建静态类的对象->创建静态公用类返回该内部对象

class Hungry{
    // 私有化类的构造器
    private Hungry(){

    }
    // 内部创建静态类的对象
    private static Hungry hungry = new Hungry();
    // 创建静态公用类返回该内部对象
    public static Hungry getHungry(){
        return hungry;
    }
}

2. 懒汉式实现

私有化类的构造器->声明当前类的静态对象,没有初始化->创建静态公用类,在类中初始化(需要用ifelse判断是否已经初始化了),并返回当前类对象的方法

class Lazy{
    private Lazy(){

    }
    private static Lazy lazy;
    /*
      创建对象分为三个步骤:
            分配内存空间
            初始化对象
            将内存空间的地址赋值给对象的引用
      但是JVM可能会对代码进行重排序,所以2和3可能会颠倒
    */
    // 这里需要注意的是有可能发生重排序,那么就可能出现return的是空值,为了避免重排序,可以加上volatile关键字
    // private static volatile Lazy lazy;
    public static Lazy getLazy(){
        if(lazy == null){ // 在锁外层再加一个条件判断是为了提高效率,这样在第一次创建了对象之后,不需要每一次都要上锁解锁
            synchronized (Lazy.class){
                if(lazy == null){
                    lazy = new Lazy();
                }
            }
        } // 这种方式是线程安全的,首先加锁,再判断静态对象是否为空,避免了重复声明对象
        
        if(lazy == null){
            lazy = new Lazy();
        } // 这种方式是线程不安全的,因为有可能有多个线程同时判空,然后重复声明对象

        return lazy;
    }
}

3. 区分饿汉式和懒汉式

饿汉式:

· 坏处是对象加载时间过长

· 好处是饿汉式是线程安全的

懒汉式:

· 好处是延迟对象的创建

· 坏处是目前写法是线程不安全的:因为有可能在进入if语句的时候可能会new多个对象-->可以改成线程安全的

三、 优点与应用

  1. 优点:由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
  2. 应用:网站的计数器、应用程序的日志应用、数据库连接池
posted on 2020-05-02 11:44  Water2Wine  阅读(148)  评论(0编辑  收藏  举报