zoukankan      html  css  js  c++  java
  • Head First 设计模式 --5 单例模式

    单例模式:确保一个类只有一个实例,并提供一个全局访问点。
    用到的设计原则:
    1、封装变化
    2、组合优于集成
    3、针对接口变成而不是针对实现
    4、为交互对象之间的松耦合设计而努力
    5、类应该对扩展开放,对修改关闭
    6、依赖抽象,而不是依赖具体类

    最简单的单例

    class Singleton {
      private static Singleton instantce;
    
      private Singleton() {}
    
      public static Singleton getInstantce() {
        if (instantce == null) {
          instantce = new Singleton();
        }
    
        return instantce;
      }
    }

    但是这样在多线程的情况下就会出问题。当两个线程同时第一次获取单例时,此时instantce还是空,会返回两个实例。

    处理多线程单例,最简单的多线程单例

    class Singleton {
      private static Singleton instantce;
    
      private Singleton() {}
    
      public static synchronized Singleton getInstantce() {
        if (instantce == null) {
          instantce = new Singleton();
        }
    
        return instantce;
      }
    }

    只是多加了一个synchronized关键字。但是这样,同步性能会降低。以后每次调用加保护都是一种累赘。但是如果应用程序可以接受这种额外负担,比如实际上调用这个方法的次数非常少,那就什么也别做,这个并不会影响多少性能。但是如果频繁的使用,可以使用下面的方法。

    class Singleton {
      private static Singleton instantce = new Singleton();
    
      private Singleton() {}
    
      public static synchronized Singleton getInstantce() {
        return instantce;
      }
    }

    这样JVM在加载这个类的时候就已经创建出来唯一的单例。

    或者利用双重检索的方法

    class Singleton {
      private static volatile Singleton instantce;
    
      private Singleton() {}
    
      public static synchronized Singleton getInstantce() {
        if (instantce == null) {
          synchronized (Singleton.class) {
            if (instantce == null) {
              instantce = new Singleton();
            }
          }
        }
        return instantce;
      }
    }

    这里为什么里面还加了一个判断,和volatile这个关键字有关,volitile可以保证一个变量在多个线程间可见性,如果两个线程同时获取一个单例,这时单例为空,第一个线程先判断,锁住Singleton,第二个线程在等待,等待的地方是判断完为空的位置,第一个线程创建完获取到了,这时已经不为空了,如果这个地方不判断还会是在创建一个,由于volitale保证变量的可见性,第二个线程感知到已经实例化完了,就不去创建,直接获取已经创建好的实例就走了。还有双重锁定的方法不能用在jdk1.2之前,现在都1.8了,一般应该不会接触到这个问题。

    还要注意一个问题,就是不同的类加载器加载这个类的时候还是会创建出不同的实例。如果程序中有多个类加载器,小心这个问题,解决的办法是自行指定类加载器。

    OO设计认为类应该只做一件事,这里单例类不仅负责管理自己的实例,还在应用程序之间充当角色。尽管如此,由类管理自己的实例的做法还是很常见的,这可以让整体设计更简单,不然还需要设计一个类来管理这个单例类,实在有点繁琐。

  • 相关阅读:
    解决CHM文件不能浏览的问题
    SAS宏功能(下)
    python一句话求素数
    SAS与DBMS系统(SqlServer)通信
    CSS3圆角
    水平居中和垂直居中
    滚动条的控制
    快来给你的桌面加一只可爱的蟑螂吧 那个人
    自己用的PHP缓存类
    jquery 全反选
  • 原文地址:https://www.cnblogs.com/badboyf/p/6212560.html
Copyright © 2011-2022 走看看