39

最近Objective-Cとそれに書かれているさまざまなライブラリを操作しているときに、2つの非常に人気のあるシングルトンパターンに気づきました。1つのバージョンはシングルトンインスタンスをフェッチしてそのインスタンスメソッドを呼び出し、他のバージョンはクラスメソッドのみを公開し、操作するインスタンスを提供しません。すべて、単一のリソース(StoreKit、CoreData、Parse APIなど)へのアクセスを抽象化することを目的としています。たとえば、MKStoreKitで使用されている以前のアプローチは次のとおりです。

// initialize singleton during app boot
[MKStoreManager sharedManager]

// sometime later in the app
[[MKStoreManager sharedManager] buyFeature:kFeatureAId 
                                onComplete:^(NSString* purchasedFeature)
 {
     NSLog(@"Purchased: %@", purchasedFeature);
 }
                               onCancelled:^
 {
     NSLog(@"User Cancelled Transaction");
 }];

または、NSUserDefaults、UIApplicationなど。他のアプローチは、MagicalRecordまたはここでParseAPIを使用して確認できます。

// configure API credentials sometime during app boot
[Parse setApplicationId:@"123456"
              clientKey:@"123456"];

// sometime later
PFObject *testObject = [PFObject objectWithClassName:@"TestObject"];
[testObject setObject:@"bar" forKey:@"foo"];
[testObject save];

2つのアプローチの長所と短所は何ですか?それらの1つは他よりも根本的に優れていますか?

共有インスタンスを取得する必要がないため、画面のスペースを節約できます(パフォーマンスの違いは関係ない可能性があります)が、テスト容易性など、他の方法で自分自身を台無しにしていますか?

ありがとう!

4

2 に答える 2

29

クラス メソッドに基づいてアプローチを実装するには、次の 2 つの方法があります。

  • 誰からも隠されているクラスを使用してシングルトン インスタンスを作成し、そのメソッドを同一のシグネチャを持つラッパー クラス メソッドの背後に隠す、または
  • すべての作業を行うクラス メソッドを作成する

最初の実装の意味は、シングルトンでできることはすべて、非表示のシングルトンでできるということです。

  • サブクラスの使用が可能になります
  • 実行中のインスタンスの切り替えは簡単です
  • 状態はインスタンス変数に存在します
  • 初期化はおなじみのパターンに従います

シングルトンを使用しない実装を選択すると、現在の状態を維持するために静的変数に依存することになります。これは正当な選択ですが、初期化パターンが異なり (おそらく a を使用してもdispatch_once)、いくつかの醜い条件に依存せずに途中で実装を切り替えることはできずif、サブクラスの使用ははるかにトリッキーになります。

最初の実装をテストする方が、2 番目の実装をテストするよりもいくらか簡単です。これは、おそらくバックドアを介して、テスト用にシングルトンの別の実装を提供できるためです。静的ベースの実装では、このルートを取ることはできません。

要約すると、シングルトン ベースのソリューションを使用し、オプションでシングルトンのメソッドへのアクセスを提供する「ファサード」の背後にシングルトンを非表示にします。すべての状態を静的変数に配置する必要がある実装は使用しません。

于 2012-11-02T04:04:27.010 に答える
7

シングルトン アプローチの利点の 1 つは、必要に応じて他のインスタンスを許可することが簡単になることです。クラス メソッド アプローチを採用する場合は、多くのリファクタリングを行わなくても、それだけで十分です。

于 2012-11-02T03:50:42.910 に答える