JAva設計モード学習ノート(五)単例モード


シングル・インスタンス・モード:ユニークで、インスタンスが1つしかないオブジェクトを作成するための入場券.
一部のオブジェクトでは、(スレッドプール、キャッシュ、ダイアログボックスなど)1つしか必要ありません.実際には、このようなオブジェクトには1つのインスタンスしかありません.製造が多くなると、動作異常、リソースの過剰使用などの多くの問題が発生します.
グローバル変数の欠点は、オブジェクトをグローバル変数に割り当てる場合、プログラムが最初からオブジェクトを作成しなければならないということです.万が一、このオブジェクトがリソースを非常に消費し、プログラムが今回の実行中に使用されなかった場合、無駄になります.
public class Singleton {
    private static Singleton uniInstance;
    public int ID;
                                                                                                                                                                                                                                                                                                                                   
    private Singleton(int id) {
        ID = id;
    }
                                                                                                                                                                                                                                                                                                                                   
    public static Singleton getInstance(int id) {
        if (uniInstance == null) {
            uniInstance = new Singleton(id);
        }
                                                                                                                                                                                                                                                                                                                                   
        return uniInstance;
    }
}
                                                                                                                                                                                                                                                                                                                                  
//----------------------Main------------------------
                                                                                                                                                                                                                                                                                                                                  
public class Main {
    public static void main(String[] args) {
        Singleton mSingleton,nSingleton;
        mSingleton = Singleton.getInstance(3);
        nSingleton = Singleton.getInstance(4);
        System.out.println(mSingleton.ID);
        System.err.println(nSingleton.ID);
    }
}

印刷された結果は,いずれも3であり,mSingletonとnSingletonが同じオブジェクトを指していることを示し,インスタンスの一意性を保証した.
このインスタンスが必要でない場合、インスタンスは永遠に生成されません.
上記は単例モードの古典的な実現であり、単例モードの定義を見る.
クラスにインスタンスが1つしかないことを確認し、グローバル・アクセス・ポイントを指定します.
クラスを独自に管理する個別のインスタンスに設計し、他のクラスがインスタンスを生成することを回避します.このインスタンスのグローバル・アクセス・ポイントが提供されます.インスタンスが必要な場合、クラスにクエリーすると、単一のインスタンスが返されます.
Singletonが宣言するインスタンスオブジェクトはグローバルでなければならないことに注意してください.上記のコードの
Singleton mSingleton,nSingleton;

それぞれ異なるスレッドに宣言されると、getInstanceで得られたインスタンスは単一モードルールに合致しません.
チョコレート工場:
/**
 *             ,     ,             ,          ,        
 */
                                                                  
public class ChocolateBoiler {
    private boolean empty;//      ,     
    private boolean boiled;
    public ChocolateBoiler() {
        empty = true;
        boiled = false;
    }
                                                                  
    /**
     *          ,       。       ,  empty boiled     
     */
    public void fill() {
        if (isEmpty()) {
            empty = false;
            boiled = true;
            //                 
        }
    }
                                                                  
    private boolean isEmpty() {
        return empty;
    }
                                                                
    private boolean isBoiled() {
        return boiled;
    }
                                                                  
    /**
     *      ,     (      )      。     , empty    true
     */
    public void drain() {
        if (!isEmpty() && isBoiled()) {
            //            
            empty = true;
        }
    }
                                                                  
    /**
     *      ,       ,        ,     ,  boiled    true
     */
    public void boil() {
        if (!isEmpty() && !isBoiled()) {
            //       
            boiled = true;
        }
    }
}

なお、ChocolateBoilerの例が2つ以上存在する場合、500リットルの主費の混合物を排除したり、ボイラーがいっぱいになっても原料を入れ続けたり、ボイラー内に原料を入れていないのに空焼を開始したりする問題がある可能性がある.次のコードを変更します.
public class ChocolateBoiler {
    private boolean empty;//      ,     
    private boolean boiled;
    private static ChocolateBoiler uniChocolateBoiler;
                                       
    private ChocolateBoiler() {
        // TODO Auto-generated constructor stub
        empty = true;
        boiled = false;
    }
                                       
    public static ChocolateBoiler getInstance() {
        if (uniChocolateBoiler == null) {
            uniChocolateBoiler = new ChocolateBoiler();
        }
        return uniChocolateBoiler;
    }
    //      
}

またトラブルに直面して、fill方法は加熱の過程で原料を続けることを許可して、これは500リットルの原料を溢れることができます.マルチスレッドによる問題です.   
マルチスレッドを処理するには、getInstance()を同期(synchronized)メソッドに変更します.
class Singleton {
    private static Singleton uniqueInstance;
                              
    private Singleton() {
    }
                              
    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}

総括する
   1.単一モードは、プログラム内のクラスが最大1つのインスタンスしかないことを保証します.
   2.単一モードでは、このインスタンスにアクセスするグローバルポイントも提供されます.
   3.Javaで単品モードを実現するには
(1)プライベートコンストラクタ
(2)静的方法
(3)静的変数
   4.パフォーマンスとリソースの制限を決定し、マルチスレッドの問題を解決するために適切なスキームを慎重に選択して単一のデバイスを実現します.
最近Golangを勉強しているので、その後学習したデザインパターンがJava特有の言語特性に触れていなければ、学習ノートのソースコードはGolangで完成します