国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

設(shè)計(jì)模式之單例模式

cnsworder / 1415人閱讀

摘要:反射攻擊首先我們來(lái)看一下反射調(diào)用,以雙重檢驗(yàn)方式為例反射攻擊輸出結(jié)果是反射攻擊結(jié)果私有構(gòu)造方法被調(diào)用次私有構(gòu)造方法被調(diào)用次從結(jié)果可以看到,私有的構(gòu)造函數(shù)被調(diào)用了兩次,也就是說(shuō)這樣的單例模式并不安全。

保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。
——艾迪生維斯理 《設(shè)計(jì)模式》
版權(quán)聲明:本文為 冬夏 原創(chuàng)發(fā)表在公眾號(hào)「Android從入門到精通」,可以隨意轉(zhuǎn)載,但請(qǐng)注明出處。
概述

在我們?nèi)粘>帉懗绦虻臅r(shí)候,經(jīng)常需要一種這樣的對(duì)象。我們希望整個(gè)系統(tǒng)只有一個(gè)這樣的對(duì)象,不論在什么時(shí)候和不論在哪里獲取這個(gè)對(duì)象的時(shí)候,獲得的都是同一個(gè)對(duì)象。

比如說(shuō)系統(tǒng)的任務(wù)管理器,我們希望整個(gè)系統(tǒng)只有一個(gè)任務(wù)管理器,不論什么時(shí)候打開任務(wù)管理器,都可以看到當(dāng)前系統(tǒng)的所有任務(wù),而不是把任務(wù)分散在很多個(gè)任務(wù)管理器里。

又比如說(shuō)打印機(jī),當(dāng)電腦連接上一臺(tái)打印機(jī)的時(shí)候,我們會(huì)希望不管是在文檔A里使用或者在文檔B里使用的時(shí)候,都是同一臺(tái)打印機(jī),而且能夠按順序打印。

我們把這種類似的需求不斷總結(jié)并歸納起來(lái),就成了單例模式。

單例模式可以說(shuō)是所有設(shè)計(jì)模式里面最簡(jiǎn)單的了,但是要靈活并且準(zhǔn)確地使用它也不是那么容易的。

首先觀察一下單例模式的 UML 圖。

從 UML 圖中我們可以觀察到單例模式的幾個(gè)特點(diǎn)

私有的、靜態(tài)的實(shí)例對(duì)象

私有的構(gòu)造函數(shù)

公有的、靜態(tài)的獲取實(shí)例對(duì)象的方法

那么,什么樣的代碼可以同時(shí)滿足這幾個(gè)特點(diǎn)呢?

懶漢模式

所謂的懶漢模式,就是一開始并不實(shí)例化對(duì)象,等到需要使用的時(shí)候才實(shí)例化。

{% codeblock 懶漢模式 lang:java %}
public class Singleton {

  private static Singleton instance = null;

  private Singleton(){}

  public static Singleton getInstance() {
      if (instance == null)
      {
          instance = new Singleton();
      }
      return instance;
  }
}
{% endcodeblock %}

從上面的代碼我們可以看到,當(dāng)?shù)谝淮潍@取 Singleton 實(shí)例的時(shí)候,instance 為空,將創(chuàng)建 Singleton 對(duì)象,并賦值給 instance 變量。以后的每次一獲取都將獲得第一次創(chuàng)建的 Singleton 對(duì)象,從而實(shí)現(xiàn)了唯一性。

線程安全驗(yàn)證

仔細(xì)想想這段代碼,可能存在什么問(wèn)題呢?

假設(shè)有這么一種情況, Singleton 對(duì)象還沒(méi)有創(chuàng)建,這時(shí)候有很多個(gè)線程同時(shí)獲取 Singleton 對(duì)象,這時(shí)候會(huì)發(fā)生什么呢?

用下面的代碼可以驗(yàn)證

{% codeblock 懶漢模式 線程安全驗(yàn)證 lang:java %}
public class Singleton {
  private static int count = 0;

  private static Singleton instance = null;

  private Singleton(){
      try {
          Thread.sleep(10);
      }catch (InterruptedException e){

      }
      System.out.println("Singleton 私有構(gòu)造方法被調(diào)用 " + ++count + "次");
  }

  public static Singleton getInstance() {
      if (instance == null)
      {
          instance = new Singleton();
      }
      return instance;
  }
}


public class Test {
  public static void main(String[] args){

      Runnable runnable = new Runnable() {
          @Override
          public void run() {
              Singleton singleton = Singleton.getInstance();
              System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() +
                      " Singleton: " + singleton.hashCode());
          }
      };

      for (int i = 0; i < 10; i++){
          new Thread(runnable).start();
      }
  }
}
{% endcodeblock %}

從上面的代碼可以看到,我們對(duì)懶漢模式做了一點(diǎn)小修正,在創(chuàng)建 Singleton 對(duì)象的時(shí)候讓當(dāng)前線程休眠了10ms,這主要是因?yàn)橛?jì)算機(jī)運(yùn)算速度太快了,不讓當(dāng)前線程休眠一下的話很難出現(xiàn)想要的結(jié)果。關(guān)于休眠我們可以把它想象成創(chuàng)建對(duì)象的過(guò)程中需要消耗一定的時(shí)間。

運(yùn)算部分結(jié)果如下:

{% codeblock 懶漢模式 線程安全驗(yàn)證結(jié)果 lang:java %}
Singleton 私有構(gòu)造方法被調(diào)用 1次
當(dāng)前線程:Thread-1 Singleton: 2044439889
Singleton 私有構(gòu)造方法被調(diào)用 4次
Singleton 私有構(gòu)造方法被調(diào)用 3次
Singleton 私有構(gòu)造方法被調(diào)用 2次
當(dāng)前線程:Thread-0 Singleton: 605315508
當(dāng)前線程:Thread-2 Singleton: 2298428
當(dāng)前線程:Thread-3 Singleton: 1005746524
當(dāng)前線程:Thread-4 Singleton: 1005746524
當(dāng)前線程:Thread-5 Singleton: 1005746524
當(dāng)前線程:Thread-6 Singleton: 1005746524
當(dāng)前線程:Thread-7 Singleton: 1005746524
當(dāng)前線程:Thread-8 Singleton: 1005746524
當(dāng)前線程:Thread-9 Singleton: 1005746524
{% endcodeblock %}

從上面的結(jié)果可以看到,Singleton 的私有構(gòu)造方法被調(diào)用了不止一次。對(duì)此的解釋是,當(dāng)?shù)谝淮潍@取 Singleton 對(duì)象還沒(méi)完成的時(shí)候,線程被系統(tǒng)掛起了,這時(shí)候有其他線程剛好也獲取了 Singleton 對(duì)象,那么就會(huì)產(chǎn)生多個(gè) Singleton 對(duì)象。

由此我們可以得出結(jié)論:懶漢模式是 非線程安全 的。

同步方法

為了解決懶漢模式非線程安全的缺點(diǎn),就出現(xiàn)了改進(jìn)的懶漢模式。其原理是當(dāng)多個(gè)線程同時(shí)獲取 Singleton 對(duì)象時(shí),一次只讓一個(gè)線程獲取,其他線程都在等待,這樣就解決了多線程下的對(duì)象獲取問(wèn)題。

{% codeblock 同步方法 lang:java %}
public class Singleton {
  private static Singleton instance = null;

  private Singleton(){}

  public static synchronized Singleton getInstance() {
      if (instance == null)
      {
          instance = new Singleton();
      }
      return instance;
  }
}
{% endcodeblock %}

我們通過(guò) synchronized 關(guān)鍵字讓 getInstance()方法一次只能讓一個(gè)線程調(diào)用,但是隨著而來(lái)的又有另外一個(gè)問(wèn)題。

那就是 效率問(wèn)題,因?yàn)橹挥械谝淮潍@取 Singleton 對(duì)象時(shí)有可能發(fā)生線程安全問(wèn)題,但是使用同步方法卻讓每次只讓一個(gè)線程能訪問(wèn)getInstance()方法,而不管 Singleton 對(duì)象是不是已經(jīng)被創(chuàng)建出來(lái)了。

那么有沒(méi)有辦法能同時(shí)解決線程安全和效率問(wèn)題呢?

雙重校驗(yàn)

雙重校驗(yàn) 方式就是為了解決懶漢模式的線程安全和效率問(wèn)題而產(chǎn)生的。

{% codeblock 雙重校驗(yàn) lang:java %}
public class Singleton {

  private static Singleton instance = null;

  private Singleton(){}

  public static Singleton getInstance() {
      if (instance == null){
          synchronized (Singleton.class){
              if (instance == null){
                  instance = new Singleton();
              }
          }
      }
      return instance;
  }
}
{% endcodeblock %}

雙重校驗(yàn)就是將前面兩種懶漢模式結(jié)合起來(lái)。當(dāng)?shù)谝淮潍@取 Singleton 對(duì)象時(shí), instance 為空, 這時(shí)候?yàn)榱私鉀Q可能存在的線程安全問(wèn)題,同步了 Singleton 這個(gè)類對(duì)象。也就是說(shuō),同一時(shí)刻只能有一個(gè)線程能夠執(zhí)行 synchronized 之后的代碼。同時(shí)因?yàn)橥酱a外層有一個(gè)條件語(yǔ)句,所以同步代碼只有在第一次獲取 Singleton 對(duì)象的時(shí)候執(zhí)行到,這樣就解決了效率問(wèn)題。

但是這種方法還是有一個(gè)問(wèn)題,那就是 instance = new Singleton() 這一行代碼并不是原子性的

具體來(lái)說(shuō),JVM執(zhí)行這一行代碼時(shí)主要做了三件事

給 instance 分配內(nèi)存空間

調(diào)用 Singleton 的構(gòu)造函數(shù)來(lái)初始化成員變量

將 instance 變量指向分配的內(nèi)存空間(執(zhí)行完這一步之后 instance 就不為 null 了)

由于 JVM 的指令優(yōu)化存在,上面的第二點(diǎn)和第三點(diǎn)并不能保證一定按順序執(zhí)行。也就是說(shuō)執(zhí)行順序有可能為 1-2-3 或者 1-3-2。

假設(shè)是 1-3-2,那么如果執(zhí)行到3的時(shí)候,線程被搶占了,有另外一個(gè)線程獲取了單例對(duì)象(這時(shí)候 instance 不為 null,但是還沒(méi)有初始化),那么自然就會(huì)出現(xiàn)錯(cuò)誤。

為了解決這個(gè)問(wèn)題,我們只要將 instance 變量聲明成 volatile 就可以了。

private static volatile Singleton instance = null;

volatile 關(guān)鍵字主要有兩個(gè)特性

可見性:保證線程沒(méi)有變量的本地副本,每次都去主內(nèi)存獲取最新版本

禁止指令重排序:生成內(nèi)存屏障

很明顯,我們這里利用的是 volatile 的第二個(gè)特性。

特別注意的是只有在 Java 5 之后使用這種方式才是完全安全的,原因是 Java 5 之前的 Java 內(nèi)存模型(Java Memory Model,JMM)存在缺陷,即使變量聲明為 volatile 也不能完全避免重排序,這個(gè)問(wèn)題在 Java 5 之后才修復(fù)。

惡漢模式

這時(shí)候我們可以換個(gè)思路,既然懶漢模式是因?yàn)樾枰臅r(shí)候才創(chuàng)建對(duì)象,所以才讓程序有機(jī)會(huì)可以產(chǎn)生多個(gè)對(duì)象。那如果我一開始就把對(duì)象創(chuàng)建好了,不就行了嗎?這就出現(xiàn)了惡漢模式。

惡漢模式的意思是不管對(duì)象目前有沒(méi)有使用,都會(huì)先創(chuàng)建出來(lái)。

{% codeblock 惡漢模式 lang:java %}
public class Singleton {

  private static final Singleton instance = new Singleton();

  private Singleton(){}

  public static Singleton getInstance() {
      return instance;
  }
}
{% endcodeblock %}

從代碼中可以看到,由于在 Singleton 類加載時(shí)就創(chuàng)建了 Singleton 對(duì)象,所以惡漢模式是 線程安全 的。

但是惡漢模式存在的問(wèn)題就是不管目前對(duì)象有沒(méi)有被使用,都被創(chuàng)建了出來(lái),浪費(fèi)了內(nèi)存空間。

靜態(tài)方法

靜態(tài)方法的單例模式和惡漢模式的原理一樣,都是利用了classloader,在類加載的時(shí)候就創(chuàng)建了 Singleton 對(duì)象。

{% codeblock 靜態(tài)方法 lang:java %}
public class Singleton {

  private static Singleton instance = null;

  static {
      instance = new Singleton();
  }
  private Singleton(){}

  public static Singleton getInstance() {
      return instance;
  }
}
{% endcodeblock %}
靜態(tài)內(nèi)部類

靜態(tài)內(nèi)部類的方法和上面兩種方法既有相似的地方,也有不同的地方。

{% codeblock 靜態(tài)內(nèi)部類 lang:java %}
public class Singleton {

  private static class SingletonHolder{
      private static final Singleton INSTANCE = new Singleton();
  }
  private Singleton(){}

  public static Singleton getInstance() {
      return SingletonHolder.INSTANCE;
  }
}
{% endcodeblock %}

從代碼種我們可以看到,靜態(tài)內(nèi)部類的方法和前兩種方法一樣,都是利用了classloader,在加載類的時(shí)候創(chuàng)建 Singleton 對(duì)象。

不同的地方在于加載的類不同。靜態(tài)內(nèi)部類方法在加載 Singleton 類的時(shí)候不會(huì)創(chuàng)建 Singleton 對(duì)象。而是在加載 SingletonHolder 類的時(shí)候才會(huì)。那么 SingletonHolder 類是什么時(shí)候加載的呢?

根據(jù)JVM(Java 虛擬機(jī))的類加載規(guī)則,靜態(tài)內(nèi)部類只有在主動(dòng)調(diào)用的時(shí)候才會(huì)加載。也就是說(shuō),在第一次調(diào)用 getInstance() 方法時(shí)才會(huì)加載 SingletonHolder 類,同時(shí)創(chuàng)建了 Singleton 對(duì)象。

也可以說(shuō),靜態(tài)內(nèi)部類的方法利用JVM解決了前兩種方法占用內(nèi)存的問(wèn)題。

防止單例受到攻擊

到目前為止,我們所分析的所有單例模式都有一個(gè)前提,那就是調(diào)用者非常聽話地使用了 Singleton.getInstance() 方法獲取單例對(duì)象。但是在現(xiàn)實(shí)生活中是不是都是這樣的呢?會(huì)不會(huì)有不懷好意的人使用其他方式破壞我們的單例模式呢?

我們先思考一下,獲取一個(gè)對(duì)象有幾種方式

使用 new 關(guān)鍵字

通過(guò)反射調(diào)用

序列化

我們前面的單例模式都是通過(guò)第一種方式獲取對(duì)象的,那么如果采用其他兩種方式,之前的單例模式還安全嗎?答案是否定的。

反射攻擊

首先我們來(lái)看一下反射調(diào)用,以雙重檢驗(yàn)方式為例

{% codeblock 反射攻擊 lang:java %}
public class Singleton {

  private static volatile Singleton instance = null;

  private Singleton(){}

  public static Singleton getInstance() {
      if (instance == null){
          synchronized (Singleton.class){
              if (instance == null){
                  instance = new Singleton();
              }
          }
      }
      return instance;
  }
}

public class Test {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException, InstantiationException{

        Singleton singleton1 = Singleton.getInstance();

        Class classType = Singleton.class;
        Constructor constructor = classType.getDeclaredConstructor(null);
        constructor.setAccessible(true);
        Singleton singleton2 = (Singleton) constructor.newInstance();
        System.out.println(singleton1 == singleton2);  //false
    }
}
{% endcodeblock %}

輸出結(jié)果是

{% codeblock 反射攻擊結(jié)果 lang:java %}
Singleton 私有構(gòu)造方法被調(diào)用 1次
Singleton 私有構(gòu)造方法被調(diào)用 2次
false
{% endcodeblock %}

從結(jié)果可以看到,私有的構(gòu)造函數(shù)被調(diào)用了兩次,也就是說(shuō)這樣的單例模式并不安全。

為了防止單例模式被反射攻擊,我們可以添加一個(gè)標(biāo)志位,在新建對(duì)象時(shí)判斷是否已經(jīng)新建過(guò)對(duì)象了。

{% codeblock 防止反射攻擊 lang:java %}
public class Singleton {

  private static boolean flag = false;

  private static volatile Singleton instance = null;

  private Singleton(){

      if (!flag){
          flag = true;
      }else {
          throw new RuntimeException("構(gòu)造函數(shù)被調(diào)用多次");
      }
  }

  public static Singleton getInstance() {
      if (instance == null){
          synchronized (Singleton.class){
              if (instance == null){
                  instance = new Singleton();
              }
          }
      }
      return instance;
  }
}
{% endcodeblock %}

當(dāng)然這種方式也有一個(gè)缺點(diǎn),那就是必須保證 Singleton.getInstance() 方法在反射之前調(diào)用,否則將不能正確獲取單例對(duì)象。

而且,既然我們可以通過(guò)反射創(chuàng)建出對(duì)象,那么也可以通過(guò)反射修改標(biāo)志位的值,這樣一來(lái),使用標(biāo)志位的方法就不能完全防止反射攻擊了。

序列化攻擊

接下來(lái)我們看一下序列化如何破壞單例模式,以惡漢模式為例。

{% codeblock 序列化攻擊 lang:java %}
public class Singleton implements Serializable{

  private static final Singleton instance = new Singleton();

  private Singleton(){}

  public static Singleton getInstance() {
      return instance;
  }
}

public class Test {
  public static void main(String[] args) throws IOException,ClassNotFoundException{

      Singleton singleton1 = Singleton.getInstance();
      Singleton singleton2;

      FileOutputStream fos = new FileOutputStream("SerSingleton.obj");
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(singleton1);
      oos.flush();
      oos.close();

      FileInputStream fis = new FileInputStream("SerSingleton.obj");
      ObjectInputStream ois = new ObjectInputStream(fis);
      singleton2 = (Singleton)ois.readObject();

      System.out.println(singleton1==singleton2);
  }
}
{% endcodeblock %}

輸出結(jié)果為 false 表明我們的單例收到了攻擊,那么如何防止這種情況呢?

我們可以在被序列化的類中添加readResolve方法

{% codeblock 防止序列化攻擊 lang:java %}
public class Singleton implements Serializable{

  private static final Singleton instance = new Singleton();

  private Singleton(){}

  public static Singleton getInstance() {
      return instance;
  }

  private Object readResolve(){
      return instance;
  }
}
{% endcodeblock %}

說(shuō)了這么多,不知道大家有沒(méi)有這樣一種感慨 「 都說(shuō)單例模式是最簡(jiǎn)單的一種模式,這么還這么復(fù)雜,以后還讓不讓人活了 」。

那么有沒(méi)有一種又簡(jiǎn)單有能防止所有攻擊的方法呢?

枚舉

枚舉( enum )是 Java1.5 之后新加的特性。

大家一定很奇怪,為什么枚舉可以實(shí)現(xiàn)單例呢?其實(shí)和 Java 的編譯特性有關(guān)。因?yàn)槊杜e是 Java1.5 之后新加的,一般新加入的功能有一個(gè)很重要的問(wèn)題需要解決,就是對(duì)以前代碼的兼容性問(wèn)題。而 Java 是通過(guò) 語(yǔ)法糖 的方式解決的。簡(jiǎn)單來(lái)說(shuō)就是編寫代碼的時(shí)候可以使用新的關(guān)鍵字 enum 編寫程序,但是 Java 編譯器在編譯成字節(jié)碼的時(shí)候,還是會(huì)利用現(xiàn)有的技術(shù)編譯成之前的 JVM 能夠識(shí)別并正確運(yùn)行的字節(jié)碼,這就是語(yǔ)法糖技術(shù)。

我們先來(lái)看一下枚舉編寫的單例是什么樣子的。

{% codeblock 枚舉 lang:java %}
public enum Singleton {

  INSTANCE;

  public static Singleton getInstance(){
      return INSTANCE;
  }

  public void otherMethods(){
      System.out.println("do something");
  }
}
{% endcodeblock %}

這段代碼看起來(lái)很簡(jiǎn)單,我們定義了一個(gè)枚舉類型 INSTANCE, 這就是我們需要的單例。但是為什么這樣就能實(shí)現(xiàn)線程安全的單例呢?要解決這個(gè)疑問(wèn),我們必須把這段代碼進(jìn)行反編譯,看看 java 編譯器究竟是如何編譯這段代碼的。

我們使用 java 自帶的反編譯工具 javap 就可以將這段代碼反編譯

javap -c Singleton

反編譯結(jié)果如下:

{% codeblock 反編譯 lang:java %}
public final class Singleton extends java.lang.Enum {
public static final Singleton INSTANCE;

public static Singleton[] values();
  Code:
     0: getstatic     #1                  // Field $VALUES:[LSingleton;
     3: invokevirtual #2                  // Method "[LSingleton;".clone:()Ljava/lang/Object;
     6: checkcast     #3                  // class "[LSingleton;"
     9: areturn

public static Singleton valueOf(java.lang.String);
  Code:
     0: ldc           #4                  // class Singleton
     2: aload_0
     3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
     6: checkcast     #4                  // class Singleton
     9: areturn

public static Singleton getInstance();
  Code:
     0: getstatic     #7                  // Field INSTANCE:LSingleton;
     3: areturn

public void otherMethods();
  Code:
     0: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
     3: ldc           #9                  // String do something
     5: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     8: return

static {};
  Code:
     0: new           #4                  // class Singleton
     3: dup
     4: ldc           #11                 // String INSTANCE
     6: iconst_0
     7: invokespecial #12                 // Method "":(Ljava/lang/String;I)V
    10: putstatic     #7                  // Field INSTANCE:LSingleton;
    13: iconst_1
    14: anewarray     #4                  // class Singleton
    17: dup
    18: iconst_0
    19: getstatic     #7                  // Field INSTANCE:LSingleton;
    22: aastore
    23: putstatic     #1                  // Field $VALUES:[LSingleton;
    26: return
}
{% endcodeblock %}

可能這段代碼對(duì)于剛剛接觸 java 的人來(lái)說(shuō)一時(shí)可能看不懂,但是我們只要關(guān)注到一下幾點(diǎn)就好了。

public final class Singleton extends java.lang.Enum 這說(shuō)明枚舉類型實(shí)際上被 java 編譯器通過(guò)語(yǔ)法糖轉(zhuǎn)換成了不可變類,繼承自 Enum 類。

public static final Singleton INSTANCE,說(shuō)明我們定義的枚舉值 INSTANCE 實(shí)際上被 java 編譯器轉(zhuǎn)換成了不可變對(duì)象,只可以初始化一次。

關(guān)注到 INSTANCE 實(shí)際上是在 static {} 這段代碼里初始化的。也就是說(shuō), INSTANCE 是在 Singleton 類加載的時(shí)候初始化的,所以一旦 Singleton 類加載了,INSTANCE 也就初始化了,不能再改變了,這就實(shí)現(xiàn)了單例模式。

然后如果我們嘗試使用序列化或者反射的方式去攻擊枚舉單例,會(huì)發(fā)現(xiàn)都不能成功,這是由于 JVM 實(shí)現(xiàn)枚舉的機(jī)制決定的。

最后,引用一下 《Effective Java》一書中的話。

單元素的枚舉類型已經(jīng)成為實(shí)現(xiàn)Singleton的最佳方法。
——《Effective Java》

歡迎關(guān)注我的個(gè)人公眾號(hào),一起學(xué)習(xí)Android、Java、設(shè)計(jì)模式等技術(shù)!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/68109.html

相關(guān)文章

  • 大話PHP設(shè)計(jì)模式單例模式升級(jí)版

    摘要:用來(lái)指向已創(chuàng)建好的實(shí)例構(gòu)造函數(shù)為空注意這里是關(guān)鍵這是我們需要調(diào)用的方法把函數(shù)也定義為空,這樣就大功告成啦。 接上一篇大話PHP設(shè)計(jì)模式之單例模式 這一篇介紹一下升級(jí)版的單例模式,廢話不說(shuō)先上代碼 不完美的單例模式 class singleMode { //用來(lái)指向已創(chuàng)建好的實(shí)例 public static $instance; //判斷是...

    darcrand 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式單例模式

    摘要:博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語(yǔ)言實(shí)現(xiàn)。單例模式用途如果一個(gè)類負(fù)責(zé)連接數(shù)據(jù)庫(kù)的線程池日志記錄邏輯等等,此時(shí)需要單例模式來(lái)保證對(duì)象不被重復(fù)創(chuàng)建,以達(dá)到降低開銷的目的。 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)...

    yy736044583 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式單例模式

    摘要:博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語(yǔ)言實(shí)現(xiàn)。單例模式用途如果一個(gè)類負(fù)責(zé)連接數(shù)據(jù)庫(kù)的線程池日志記錄邏輯等等,此時(shí)需要單例模式來(lái)保證對(duì)象不被重復(fù)創(chuàng)建,以達(dá)到降低開銷的目的。 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)...

    lijy91 評(píng)論0 收藏0
  • 大話PHP設(shè)計(jì)模式單例模式

    摘要:上面是簡(jiǎn)單的單例模式,自己寫程序的話夠用了,如果想繼續(xù)延伸,請(qǐng)傳送至大話設(shè)計(jì)模式之單例模式升級(jí)版 看了那么多單例的介紹,都是上來(lái)就說(shuō)怎么做,也沒(méi)見說(shuō)為什么這么做的。那小的就來(lái)說(shuō)說(shuō)為什么會(huì)有單例這個(gè)模式以便更好的幫助初學(xué)者真正的理解這個(gè)設(shè)計(jì)模式,如果你是大神,也不妨看完指正一下O(∩_∩)O首先我不得不吐槽一下這個(gè)模式名字單例,初學(xué)者通過(guò)字面很難理解什么是單例,我覺(jué)得應(yīng)該叫唯一模式更貼切...

    VEIGHTZ 評(píng)論0 收藏0
  • 優(yōu)才公開課筆記:php設(shè)計(jì)模式(一) 單例模式

    摘要:最近開展了三次設(shè)計(jì)模式的公開課,現(xiàn)在來(lái)總結(jié)一下設(shè)計(jì)模式在中的應(yīng)用,這是第一篇?jiǎng)?chuàng)建型模式之單例模式。不過(guò)因?yàn)椴恢С侄嗑€程所以不需要考慮這個(gè)問(wèn)題了。 最近開展了三次設(shè)計(jì)模式的公開課,現(xiàn)在來(lái)總結(jié)一下設(shè)計(jì)模式在PHP中的應(yīng)用,這是第一篇?jiǎng)?chuàng)建型模式之單例模式。 一、設(shè)計(jì)模式簡(jiǎn)介 首先我們來(lái)認(rèn)識(shí)一下什么是設(shè)計(jì)模式: 設(shè)計(jì)模式是一套被反復(fù)使用、容易被他人理解的、可靠的代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。 設(shè)計(jì)模式不...

    guyan0319 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式單例模式

    摘要:原文博客地址單例模式系統(tǒng)中被唯一使用,一個(gè)類只有一個(gè)實(shí)例。中的單例模式利用閉包實(shí)現(xiàn)了私有變量?jī)烧呤欠裣嗟热躅愋停瑳](méi)有私有方法,使用者還是可以直接一個(gè),也會(huì)有方法分割線不是單例最簡(jiǎn)單的單例模式,就是對(duì)象。 原文博客地址:https://finget.github.io/2018/11/06/single/ 單例模式 系統(tǒng)中被唯一使用,一個(gè)類只有一個(gè)實(shí)例。實(shí)現(xiàn)方法一般是先判斷實(shí)例是否存在,...

    lk20150415 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<