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

  • 相关阅读:
    metal的gpu query
    体积雾 global fog unity 及改进
    hdr rt format对颜色的影响
    unity deferred lighting
    unity linear space时 photoshop blend的正确设置
    unity linear work flow
    一些数据 bandwidth之类
    deferred rendering with msaa
    unity 显示mipmaplevel
    【转】在C#中使用SendMessage
  • 原文地址:https://www.cnblogs.com/badboyf/p/6212560.html
Copyright © 2011-2022 走看看