『Effective Java中国語版第2版』第2章第3条:プライベートコンストラクタまたは列挙タイプでSingleton属性を強化する

2314 ワード

この章では、オブジェクトの作成と破棄について説明します.オブジェクトの作成方法、作成を回避する方法、適切に破棄できるようにする方法、オブジェクトの破棄前に行わなければならないさまざまなクリーンアップを管理する方法について説明します.
[toc]
Singletonとは、一度だけインスタンス化されたクラスを指す.クラスをSingletonにすると、そのタイプのインタフェースとして機能しない限り、Singletonにシミュレーションインスタンスを置き換えることができないため、クライアントのテストが困難になります.
Java 1.5リリースの前にSingletonを実現するには2つの方法があります.
どちらの方法も、コンストラクタをプライベートに維持し、クライアントがクラスの一意のインスタンスにアクセスできるように、共通の静的メンバーをエクスポートします.
パブリックドメイン(public-field)メソッド:パブリック静的メンバーはfinalドメインです.
//Singleton with public final field

public class Elvis {

    public static final Elvis INSTANCE = new Elvis( );

    private Elvis( ) { ... }

    public void leaveTheBuilding( ) { ... }

}

プライベートコンストラクタは、共通の静的finalドメインElvis.INSTANCをインスタンス化するために1回のみ呼び出されます.共有または保護されたコンストラクタが欠けているため、グローバル一意性は保証されますが、反射法によってプライベートコンストラクタを呼び出すことができます.反射攻撃を防ぐには、コンストラクタを変更して、2番目のインスタンスを作成するときに例外を放出します.
メリット:
  • クラスを構成するメンバーの宣言は、このクラスがSingletonであることを明確に示している.
  • パブリックドメインメソッドでは、パフォーマンス上の利点はありません.【現代のJVM実装では、ほとんど静的ファクトリメソッドの呼び出しをインライン化することができます】.

  • 静的ファクトリメソッド:共有メンバーは静的ファクトリメソッドです.
    // Singleton with static factory
    
    public class Elvis {
    
        private static final Elvis INSTANCE = new Elvis( );
    
        private Elvis( ) { ... }
    
        public static Elvis getInstance( ) { return INSTANCE; }
    
        public void leaveTheBuilding( ) { ... }
    
    }
    

    静的メソッドElvis.getInstanceのすべての呼び出しでは、同じオブジェクト参照が返されます.反射攻撃に注意してください.
    メリット:
  • は、APIを変更することなく、クラスがSingletonであるべきかどうかを変更できる柔軟性を提供しています.【例えば、このメソッドを呼び出す既成の各々に変更して一意のインスタンスを返す】
  • 汎用利点:メソッドを呼び出すときの形式タイプパラメータに基づいて、形式タイプパラメータタイプのインスタンスを返し、複数回のインスタンスの作成を避ける【汎用を知っていれば、114ページの下~115ページの汎用単例工場モードの紹介を読むことができ、汎用の関連用語は本102ページの表の中で、本は本章の内容と一致せず、言うまでもない】
  • 以上の方法で実現したSingletonクラスを直列化可能(Serializable)(第11章参照)にするためには,宣言に「implements Serializable」を付けるだけでは不十分である.すべてのインスタンスドメインが瞬時(transient)であることを宣言し、readResolveメソッドを提供する必要があります.この方面の資料はたくさんあって、紙面の原因、自分でよく使って検索してください、ここは私がその時調べたことを提供します:点私は調べます
    Java 1.5リリース版からSingletonを実現するには3つ目の方法があります.
    単一の要素を含む列挙タイプを作成します.
    // Enum singleton - the preferred approach
    
    public enum Elvis {
    
        INSTANCE;
    
        public void leaveTheBuilding( ) { ... }
    
    }
    

    この方法は機能的に公有ドメイン法に近いが,複雑なシーケンス化や反射攻撃に直面した場合でも,シーケンス化機構をより簡潔に無償で提供し,複数回のインスタンス化を絶対に防止する.この方法はまだ広く用いられていないが,単一要素の列挙タイプはSingletonを実現するための最良の方法となっている.