Objective-Cのいわゆる「クラスクラスター」とは正確には何ですか?


91

私はNSArrayがまさにそのようなものであることを読んでいました。重いですね。私の机の上にはObjective-C、Cocoa、およびCについての本当に太った本が7冊あります。それらのどれもクラスクラスターについてまったく言及していません。少なくとも、本の後ろにある索引では見つけることができません。それでそれは何ですか?


おっと、次回はその用語のリンクを追加しようと思います。あなたが前の質問への答えにコメントしたとしたら、私はそこで答えたでしょう。
Georg Fritzsche、

2
FWIW:最近(2013年12月)Appleは、iOS 7の使用中にiOS 6への下位互換性を処理する方法としてクラスクラスターを使用することを推奨しました。これは、セッション「Architecting Modern Apps、Part 2」のApple Tech Talks 2013 / Berlinで行われました。Appleは、最後のイベントの直後(12月17日)にセッションのビデオを投稿すると発表した。したがって、おそらくこれは、iOS 6/7の変更の実際のコンテキスト内でクラスクラスターを理解するのに役立ちます。
ブレインレイ2013

回答:


42

Appleのドキュメントから...。要するに、これはFoundationフレームワークで使用されるデザインパターンです。そのため、ObjCの本には記載されていません。

クラスクラスターは、パブリックな抽象スーパークラスの下に、多くのプライベートな具象サブクラスをグループ化するアーキテクチャです。このようにクラスをグループ化すると、一般に公開されているアーキテクチャのみを表示するユーザーに、簡略化されたインターフェースが提供されます。


1
roflmao。ありがとう。次回はグーグル。私の太った本に載っていないとしても、それはあなたの頭にしかあり得ません;)
openfrog

1
このリンクが欠けているのは、ARCの実装を最適に変更する方法の説明です。
Hyperbole

193

Steveが参照したCDPの内容はわかりませんが、基本的にはObjective-Cクラスクラスターは、抽象的なFactoryパターンの実装をサポートする構造です。

アイデアは単純です:あなたは、最小限の記述で、満たすクラスタ家族の行動は、工場(クラスタ)インターフェースによって記述することをファクトリオブジェクトの特定の具体的なインスタンスを製造して返す、という工場(クラスタ)のインターフェイスを提供したいです。

簡単な具体例:この例は、特定の笑いタイプの具体的なクラス(Guffaw、Giggleなど)を生成するLaughファクトリーを提供します。笑いのinitWithLaughter:メソッドに注意してください

Laugh.hで:

#define kLaughWithGuffaw  1
#define kLaughWithGiggle  2

@interface Laugh: NSObject {}
- (Laugh *) initWithLaughter:(NSUInteger) laughterType;
- (void) laugh;
@end

Laugh.mで:

@interface Guffaws:Laugh {}
- (void) laugh;
@end

@interface Giggles:Laugh {}
- (void) laugh;
@end

@implementation Laugh
- (Laugh *) initWithLaughter:(NSUInteger) laugherType {
    id instanceReturn=nil;
    ; // Removed for ARC [self release]
    if ( laughterType == kLaughWithGuffaw )
        instanceReturn = [[Guffaws alloc]init];
    else if( laughterType == kLaughWithGiggle )
        instanceReturn = [[Giggles alloc]init];
    else
        ; // deal with this
    return instanceReturn;
}

- (void) laugh {
    NSLog(@"Humbug");
}
@end

@implementation Guffaws
    - (void) laugh {
        NSLog(@"OH HA HA HOWAH HA HA HA");
    }
@end

@implementation Giggles
    - (void) laugh {
        NSLog(@"Tee hee");
    }
@end

24
他の回答はドキュメントとブックのリンクを提供するのに適していましたが、実際にこれを行う方法を確認するのが簡単で簡単になるので、私はこれが好きです。ありがとう
jamone

この例は良いですが、典​​型的なFactoryパターンでは、サブクラスはパブリックです。クラスクラスターでは、サブクラスはプライベートです。developer.apple.com/library/ios/documentation/general/...
MaxPowerに

1
@AdriàNavarroで宣言されているため、外部からは見えません.m-file
hfossli 2014年

4
(1)initメソッド内で自分自身を解放し、別のものを返すことはどのくらい安全ですか?これを行うAppleのコード例はありますか?(2)また、のようなコードでインスタンスを作成していると考えられ[[Laugh alloc] initWithLaughter:kLaughWithGiggle]ます。Laughこの呼び出しの直後に解放されるため、が不必要に割り当てられていることに注意してください。[Laugh laughWithLaughter:kLaughWithGiggle]上記の問題1と2を回避しながら、プライベートサブクラスのすべての利点を提供するようなクラスメソッドを作成できるのに、なぜこのようにするのですか?
センスフル2014年

1
@センスフルそうです。実際に+allocは、さまざまな-initWith:メソッドを実装するシングルトンファクトリクラスを返します。次に、ファクトリクラスの-initWith:メソッドは、必要に応じて、指定されたメソッドパラメータに基づいて具象サブクラスの割り当てと初期化を行うか、場合によっては何も割り当てないことがあります(など-[NSString initWithString:])。あなたはの戻り値で検査することによって、それを試すことができ+[NSString alloc]+[NSArray alloc]など
ダレン・

25

用語集のクラスターの498ページにあるスティーブンコチャンによる目的cのプログラミングから:

プライベートコンクリートサブクラスのセットをグループ化する抽象クラス。抽象クラスを通じてユーザーに簡略化されたインターフェースを提供します。


5
+1特に元の質問が与えられた場合、Objective-Cの本からの回答を引用するため。それも良い本です。
Quinn Taylor、

(+1)優れた定義。私がこれを「ファクトリー」パターンと呼ぶことに伴う問題は、そのような名前はオブジェクトの作成にのみ焦点を当てていることであり、抽象スーパークラスによって管理されるプライベートサブクラスの内部の相互作用ではありません。実際、このスーパークラスを「抽象」と呼んでも、実際には(内部で)独自のサブクラスに大きく依存しているため、誤解を招く可能性があり、通常、そのサブクラスについて何も知らない通常の抽象クラスではありません。
devios1 2015年

18

クラスクラスターは、具体的なプライベートサブクラス実装のグループに単一のパブリックインターフェイスを提供します。Objective-Cプログラマーはクラスクラスターを頻繁に使用し、ほとんど実現しません。これがクラスクラスターの要点です。クラスクラスターの仕事は、パブリックインターフェイスの背後にある実装の詳細の複雑さを隠すことです。

Foundationクラスの多くは、NSString、NSArray、NSDictionary、NSNumberなどのクラスクラスターです。[NSString stringWithFormat:]クラスクラスターを呼び出すと、NSStringインターフェイスを実装する具体的なクラスが提供されます。それができるNSConcreteStringNSCFStringNSFooBarString、など、どのクラスクラスタを使用すると、コンストラクタに基づくか、呼び出しと引数されている初期化子されいます。

このため、クラスクラスターは、Objective-Cプログラミングで最も強力な概念の1つです。

  • 実装が非常に簡単
  • それを呼び出すコードを変更することなく、基礎となる実装を簡単に変更できます。
  • 実行時にさまざまな具体的な実装を簡単に提供できる(つまり、テストリソースまたはモックオブジェクト)
  • 上記により、テストとリファクタリングが容易

他の言語を使用している場合は、Gang of Fourパターンに精通している可能性があります。クラスクラスターには、抽象ファクトリとファサードパターンの両方の要素があります。

Appleの公開ドキュメントは、クラスクラスター(およびそれらを実装および拡張する方法)を非常に広範囲にカバーしています。残念ながら、多くのiOS開発者にとって、これと他のCocoa固有のパターンは盲点であることがわかりました。

Cocoaコアコンピテンシー:クラスクラスター

Cocoa基礎ガイド:クラスクラスタ

独自のクラスクラスターを実装する方法の例は、GitHubで入手できます。


7

NSArrayクラスのクラスターは「重い」ものではありません。これは、特定の実装をコードが認識したり気にかけたりせずに、配列クラスの任意の数の実装を使用する方法です。内部的には、NSArrayの具体的なサブクラスがあり、それらは、大規模なスパース配列や、コンパイル時に既知の特定の数の要素を含む配列など、さまざまなユースケースに適しています。

NSArray、NSString、およびNSNumberは、最も頻繁に遭遇するクラスクラスターです。


6
皮肉なことに、実際には、クラスターごとに1つの具象クラス(NSCF {Array | String | Number})のみが使用され、実装の変更はそのクラスの内部にあります。とにかく、それは私の知る限りです。NSArrayとNSMutableArrayのインスタンスでも同じクラスが表示されます。
Chuck

1
@チャック-これはどういうわけですか?NSMutableArrayとNSArrayが同じクラスであると報告された場合、[myArray isKindOfClass:[NSMutableArray class]]YES が返されないはずですが、返されませんか?
ロバート

1
@ロバート:そして、確かにそれは私のコメントの時点でそうでした。最近、AppleはNSCFArrayを__NSArrayMと__NSArrayIに置き換えたので、そうではないと思いますが、いつでも再び変更できるので、それに依存するのは快適ではありません。
チャック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.