JAVAでよく使われるいくつかのデザインモデル--単例

9146 ワード

この間の面接でデザインパターンを聞かれたんですが、結果的に単例とか工場とかしか知らないんですね….設計モード:簡単に言えば、先人が残した経験であり、コードの多重化率を高め、可読性を高めるのに役立つ.単例モードは比較的に多くのモードの1つを使うべきで、多くの人はすべて1知半解で、その中に私も含まれて、ハハ
単一モード
定義:クラスにインスタンスが1つしかなく、グローバル・アクセス・ポイントが1つしかないことを確認します.利点:クラスのインスタンスは1つしかありません.グローバル共有;オブジェクトの作成時間を短縮します.
七つの書き方
単例のモードの各種の書き方は実は有利で弊害があって、簡単な分析の下で
餓漢モード
public class Singleton {  
     private static Singleton instance = new Singleton();  
     private Singleton (){
     }
     public static Singleton getInstance() {  
         return instance;  
     }  
 }

クラスがロードされると作成され、空間で時間を変える方法です.
JAvaのruntimeクラスは餓漢モードを採用しています
public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class Runtime are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the Runtime object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /** Don't let anyone else instantiate this class */
    private Runtime() {}

    //      
}

まとめ:この方式は簡単で乱暴で、メモリの消費量が少なく、ロード時間が短い部分の単例ではこの方式を使用することができます.ただし、起動時間に要件があり、メモリリソースを多く消費するクラスでは推奨されません.
怠け者モード
  • 非スレッドセキュリティ
    public class Singleton {  
      private static Singleton instance;  
      private Singleton (){
      }   
      public static Singleton getInstance() {  
          if (instance == null) {  
              instance = new Singleton();  
          }  
          return instance;  
      }  
    }
    怠け者モードは、最初のロード時にインスタンス化される静的オブジェクトを明らかにした.遅延ロードされましたが、スレッド以外は安全で、複数のオブジェクトインスタンスが作成される可能性があります.
  • スレッドセキュリティ
  • public class Singleton {  
          private static Singleton instance;  
          private Singleton (){
          }
          public static synchronized Singleton getInstance() {  
              if (instance == null) {  
                  instance = new Singleton();  
              }  
              return instance;  
          }  
     }
    
    

    この方式ではgetInstance()メソッドに同期ロックが付加されているため、マルチスレッドの場合はスレッドがブロックされ、大量のスレッドを外にロックし、1つのスレッドが実行されてから次のスレッドが実行される.getInstanceをロックすると実行効率が低いためです.
  • スレッドセキュリティ、デュアルチェックロック
  • 
    public class Singleton {
    
        /**
         *            volatile,
         *  volatile       ,          ,
         *                    ,                 。
         */
        private volatile static Singleton singleton;
        private Singleton() {
        }
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized(Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    

    この書き方はgetSingleton()メソッドでsingletonを2回空にし,1回目は不要な同期のため,2回目はsingletonがnullに等しい場合にインスタンスを作成する.二重チェックロック:スレッドの安全を達成することもできるし、性能に大きな影響を与えないこともできる.言い換えれば、スレッドの安全を保証する前提の下で、空間を節約し、時間を節約し、「餓漢式」と二つの「怠け者式」の長所を集め、その精華を取り、その溝を取り除く.
    volatileキーワードについては、まだ多くの議論があります.volatileキーワードは、仮想マシン内の必要なコード最適化をブロックする可能性があるため、実行効率はそれほど高くありません.すなわち,「二重チェックロック」メカニズムを用いてスレッドセキュリティの一例を実現できるが,大量採用は推奨されず,状況に応じて選択できる.そしてjava 1.4および以前のバージョンでは、多くのJVMがvolatileキーワードの実装に関する問題で、「二重チェック・ロック」の失敗を招くため、「二重チェック・ロック」メカニズムはjava 1にのみ使用できる.5以上のバージョン.
  • 静的内部クラス
  • 多くの場合、javaは同期の制御を提供してくれます.たとえばstatic{...}ブロックがデータを初期化する場合.final変数がアクセスされたとき.
    JVMでクラスのロードを行うと、データが同期されることを保証するため、内部クラスを採用し、この内部クラスでオブジェクトインスタンスを作成することができます.これにより、アプリケーションで内部クラスJVMを使用しない限り、このインスタンスクラスはロードされず、インスタンスオブジェクトも作成されず、「怠け者」の遅延ロードとスレッドセキュリティが実現されます.
    public class Singleton { 
        private Singleton(){
        }
          public static Singleton getInstance(){  
            return SingletonHolder.sInstance;  
        }  
        private static class SingletonHolder {  
            private static final Singleton sInstance = new Singleton();  
        }  
    }
  • 列挙
  • 「Javaとモード」では、列挙を用いて単一インスタンス制御を実現することはより簡潔であり、シーケンス化メカニズムを無償で提供し、JVMによって根本的に保障され、複数回のインスタンス化を絶対に防止し、より簡潔で効率的で安全な単一例を実現する方法であると著者は書いている.
    public enum Singleton {
         //         ,    Singleton      
         INSTANCE;  
    
         public void doSomeThing() {  
             // do something...
         }  
     }
    

    使用方法:
    public static void main(String args[]) {
        Singleton singleton = Singleton.instance;
        singleton.doSomeThing();
    }

    実現は簡単だが、可読性の比較が悪い.
  • 使用容器
  • public class SingletonManager { 
      private static Map objMap = new HashMap();
      private Singleton() { 
      }
      public static void registerService(String key, Objectinstance) {
        if (!objMap.containsKey(key) ) {
          objMap.put(key, instance) ;
        }
      }
      public static ObjectgetService(String key) {
        return objMap.get(key) ;
      }
    }

    このことはSingletonManagerで複数の単例クラスを一括管理し,使用時にkeyに従ってオブジェクト対応タイプのオブジェクトを取得する.この方法により、複数のタイプの単一の例を管理することができ、使用時に統一されたインタフェースで取得操作を行うことができ、ユーザーの使用コストを低減し、ユーザーに具体的な実装を隠し、結合度を低減することができる.
    まとめ:以上の7つの単例について,それぞれ「餓漢式」,「怠け者式(非スレッド安全)」,「怠け者式(スレッド安全)」,「二重チェックロック」,「静的内部類」,「列挙」および「容器類管理」であった.多くの場合、人の好みによって異なり、二重検査には一定の弊害と問題があるが、私は二重検査が好きで、この方式は可読性が高く、安全で、優雅だと思っている(個人的な観点).