シングルトンパターンは、最も広く使用されているパターンの1つです。このパターンを適用する場合、シングルトンオブジェクトのクラスは、インスタンスが1つだけ存在することを確認する必要があります。多くの場合、システム全体に必要なグローバルオブジェクトは1つだけです。これは、システムの全体的な動作を調整するのに役立ちます。
基本知識
定義
特定のクラスのインスタンスが1つしかないことを確認し、それ自体をインスタンス化して、このインスタンスをシステム全体に提供します。
UML
要素
- コンストラクターは外部に公開されておらず、通常はプライベートです。
- 静的メソッドまたは列挙型を介してシングルトンオブジェクトを返します
- 特にマルチスレッド環境では、シングルトンクラスのオブジェクトが1つだけであることを確認してください
- デシリアライズ時にシングルトンクラスオブジェクトがオブジェクトを再構築しないことを確認します
シングルトンパターンの種類
シングルトンデザインパターンは、空腹のスタイル、怠惰なスタイル、静的な内部クラス、列挙、およびコンテナの実装に分けられます。
空腹の中国人
public class Singleton{
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
注:インスタンスはgetInstance()メソッドを呼び出す前に作成されているため、空腹の中国語スタイルはスレッドセーフです。
怠け者
怠惰な原型
public class Singleton {
private static Singleton singleton=null;
private Singleton(){}
public static Singleton getInstance() {
if (singleton== null) {
singleton= new Singleton();
}
return singleton;
}
}
備考:この種のレイジースタイルはスレッドセーフではなく、複数のシングルトンインスタンスが並行環境に表示される可能性があります。
スレッドの不安定性の理由:同時実行性が高い場合、スレッドAはsingleton = new Singleton()まで実行されますが、オブジェクトをまだ取得しておらず(オブジェクトの初期化には時間がかかります)、2番目のスレッドBも実行されています((シングルトン== null)判定、スレッドBは判定条件も真であるため、実行を継続し、スレッドAはオブジェクトを取得し、スレッドBもオブジェクトを取得します。メモリには2つのオブジェクトがあります。
スレッドセーフな怠惰
- getInstanceメソッドに同期を追加します
public class Singleton{
private static Singleton instance;
private Singleton(){}
// 为了在多线程情况下保证单例对象唯一性,添加了synchropized关键字
public static synchropized Singleton getInstance(){
if(instance==null){
instance==new Singleton();
}
return instance;
}
}
備考:シングルトンは使用時にのみインスタンス化されるため、ある程度のリソースを節約できます。最初にロードするときにインスタンス化する必要があり、応答がわずかに遅くなります。最大の問題は、 getInstanceが呼び出されると、同期されます。必要な同期オーバーヘッド
- ダブルチェックロック(DCL)(推奨)
public class Singleton{
private volatile static Singleton sinstance=null;
private Singleton(){}
public static Singleton getInstance(){
// 对instance进行了两次判空:第一层判断主要是为了避免不必要的同步,第二层的判断则是为了在null的情况下创建实例
if(sinstance==null){
synchropized(Singleton.class){
if(sinstance==null){
sinstance=new Singleton();
}
}
}
return sinstance;
}
}
備考:リソース使用率が高い。getInstanceを初めて実行するとシングルトンオブジェクトがインスタンス化され、効率が高くなります。最初のロードでは応答がわずかに遅くなり、Javaメモリモデルが原因で失敗することがあります。 。発生の可能性は低いですが、同時実行性の高い環境にも特定の欠陥があります。
静的内部クラス
public class Singleton{
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.sInstance;
}
// 静态内部类
private static class SingletonHolder{
private static final Singleton sInstance=new Singleton();
}
}
注:シングルトンクラスが初めてロードされるとき、sInstanceは初期化されません。getInstanceメソッドへの最初の呼び出しのみがsInstanceを初期化します。したがって、getInstanceメソッドを最初に呼び出すと、仮想マシンはSingletonHolderクラスを追加します。このメソッドは、スレッドセーフを実現し、シングルトンオブジェクトの一意性を確保するだけでなく、シングルトンのインスタンス化を遅らせます。
列挙する
public enum SingletonEnum{
INSTANCE;
public void doSomething(){
// 具体操作
}
}
備考:スレッドセーフ
コンテナはシングルトンパターンを実装します
public class SingletonManager{
private static Map<String,Object> objMap=new
HashMap<String,Object>();
pricate SingletonManager() {}
public static void registerService(String key,Object instance){
if(!objMap.containsKey(key)){
objMap.put(key);
}
}
public static Object getService(String key){
return objMap.get(key);
}
}
備考:このメソッドは、複数のタイプのシングルトンを管理し、統一されたインターフェイスを介して操作を取得できます。これにより、ユーザーのコストが削減され、特定の実装がユーザーから隠され、結合の度合いが軽減されます。
長所と短所
利点-
シングルトンモードのメモリにはインスタンスが1つしかないため、特にオブジェクトを頻繁に作成および破棄する必要があり、作成または破棄中にパフォーマンスを最適化できない場合に、メモリコストが削減されます。シングルトンモードの利点は非常に明白です。
-シングルのためサンプルモードではインスタンスが1つしか生成されないため、システムのパフォーマンスオーバーヘッドが削減されます。構成の読み取りや他の依存オブジェクトの生成など、オブジェクトの生成にさらに多くのリソースが必要な場合は、シングルを直接生成できます。アプリケーションが起動したときのインスタンス。オブジェクトの例。次に、メモリに常駐する永続的な方法を使用して解決し
ます。メモリにはインスタンスが1つしかないため、ファイルの書き込み操作など、リソースの複数の割り当てを回避するためのシングルトンパターン。リソースと同時にファイル書き込み
-シングルトンパターンは、グローバルアクセスポイント、最適化、共有リソースへのアクセスのシステムで設定できます。たとえば、すべてのデータマッピングテーブルの
欠点 を処理するシングルトンクラスを設計できます
-シングルトン一般インターフェースがない、拡張するのが難しい、拡張するコードを変更することに加えて、基本的に達成するための2番目の方法はありません
-シングルトンオブジェクトがコンテキストを保持している場合、メモリリークを引き起こしやすいです。現時点では、シングルトンオブジェクトに渡されるコンテキストに注意を払う必要があります。できればアプリケーションコンテキストです。
該当シーン
リソースを大量に消費する複数のオブジェクトが生成されないように、特定のクラスのシーンにオブジェクトが1つしかないことを確認してください。または、特定のタイプのオブジェクトが1つだけ存在する必要があります。例:オブジェクトの作成は、IOやデータベースなどのリソースへのアクセスなど、多くのリソースを消費します。
参照
- Androidのソースコードデザインパターン分析と実際の戦闘
- デザインパターンの禅