Що таке так званий «кластерний кластер» у Objective-C?


91

Я читав, що NSArray - це просто така річ. Звучить важко. На моєму столі у мене 7 справді товстих книжок про Objective-C, Cocoa та C. Жодна з них взагалі не згадує кластер класів, принаймні, я не можу знайти його в Індексі на кінці книг. То що це?


На жаль, наступного разу я подумаю додати посилання на цей термін. Якби ви прокоментували відповідь на ваше попереднє запитання, я б відповів там.
Georg Fritzsche

2
FWIW: нещодавно (грудень 2013 р.) Apple рекомендувала використовувати кластери класів як спосіб обробки зворотної сумісності з iOS 6 під час використання iOS 7. Це було на Apple Tech Talks 2013 / Берлін у сесії "Архітектура сучасних програм, частина 2". Apple заявила, що вони будуть розміщувати відеозаписи сесій незабаром після останньої події (17. грудня). Тож, можливо, це допоможе зрозуміти кластери класів у реальному контексті змін iOS 6/7.
brainray

Відповіді:


42

З документації Apple, ... . Коротше кажучи, це шаблон дизайну, що використовується в рамках Foundation, і, мабуть, саме тому він не згадується в книгах ObjC.

Кластер класів - це архітектура, яка групує низку приватних конкретних підкласів під загальнодоступним абстрактним суперкласом. Групування класів таким чином забезпечує спрощений інтерфейс для користувача, який бачить лише загальнодоступну архітектуру.


1
рофльмао. Дякую. Погуглю наступного разу. думав, якщо це не в моїх товстих книгах, це може бути тільки на ваших головах;)
openfrog

1
Єдине, чого бракує цього посилання, - це пояснення, як найкраще змінити реалізацію ARC.
Гіпербола

193

Я не знаю, що є в CDP, на який посилався Стів, але в основному кластер класу Objective-C - це конструкція, яка підтримує реалізацію абстрактного шаблону Factory .

Ідея проста : Ви хочете , щоб забезпечити завод (кластер) інтерфейс, з мінімальним описом, виробляє і повертають певний конкретний екземпляр об'єкта Factory , який задовольняє поведінка сімейства кластерів , описане інтерфейс Factory (Cluster).

Простий конкретний приклад : Цей приклад пропонує фабрику Laugh, яка виробляє конкретні класи конкретних типів сміху (наприклад, Guffaw, Giggle). Зверніть увагу на метод Laugh initWithLaughter:.

На сміх. H:

#define kLaughWithGuffaw  1
#define kLaughWithGiggle  2

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

У сміху:

@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

Цей приклад хороший, але за типовим заводським зразком підкласи є загальнодоступними. У кластері Class підкласи є приватними. developer.apple.com/library/ios/documentation/general/…
maxpower

1
@ AdriàNavarro Вони не видно зовні, оскільки вони оголошені в .m-file.
hfossli

4
(1) Наскільки безпечно звільнити себе в initметоді і повернути щось інше? Чи є приклади коду від Apple, де вони це роблять? (2) Крім того, ви, мабуть, створюєте примірник з кодом, таким як [[Laugh alloc] initWithLaughter:kLaughWithGiggle]. Зверніть увагу, як Laughрозподіляється без потреби, оскільки він буде випущений відразу після цього дзвінка. Навіщо це робити так, коли ви можете створити метод класу, такий як той, [Laugh laughWithLaughter:kLaughWithGiggle]який надає вам усі переваги приватних підкласів, уникаючи при цьому вищезазначених питань 1 і 2?
Почутливий

1
@Senseful Ви маєте рацію. У реальному житті +allocповертає фабричний клас-синглтон, який реалізує різні -initWith:методи. Тоді -initWith:методи заводського класу відповідають за виділення та ініціалізацію конкретного підкласу на основі заданих параметрів методу, якщо це необхідно, або в деяких випадках можуть взагалі нічого не виділяти (наприклад -[NSString initWithString:]). Ви можете спробувати його, перевіряючи на яке значення +[NSString alloc], +[NSArray alloc]і т.д.
Даррен

25

З програмування в цілі с Стівена Кочана на сторінці 498 у глосарії, кластер:

Абстрактний клас, який групує набір приватних конкретних підкласів, забезпечуючи спрощений інтерфейс для користувача через абстрактний клас.


5
+1 за цитування відповіді з книги Objective-C, особливо з огляду на вихідне запитання. Це теж хороша книга.
Quinn Taylor

(+1) за відмінне визначення. Проблема, з якою я маю називати цей шаблон "Фабрика", полягає в тому, що така назва зосереджена лише на створенні об'єктів, а не на взаємодії приватних підкласів під управлінням абстрактного суперкласу. Дійсно, навіть називати цей суперклас "абстрактним" може ввести в оману, оскільки він насправді цілком (внутрішньо) залежить від власних підкласів, а отже, не є звичайним абстрактним класом, який загалом нічого не знає про свої підкласи.
devios1

18

Кластери класів забезпечують єдиний загальнодоступний інтерфейс для групи конкретних реалізацій приватного підкласу. Програміст-c використовує кластери класів часто і рідко усвідомлює це - і в цьому вся суть кластера класів. Завдання кластера класів - приховувати складність деталей реалізації за загальнодоступним інтерфейсом.

Багато класів Foundation - це кластери класів, такі як NSString, NSArray, NSDictionary та NSNumber. Коли ви викликаєте [NSString stringWithFormat:]кластер, кластер дає вам конкретний клас, який реалізує NSStringінтерфейс. Це може бути NSConcreteString, NSCFString,NSFooBarString і т.д. Який клас кластер дає на основі конструктора або ініціалізатор ви дзвоните і аргументи.

Через це кластери класів є однією з найбільш розширених концепцій програмування Objective-C.

  • Дуже проста у реалізації
  • Легко змінити базову реалізацію, не змінюючи код, який її викликає.
  • Легко забезпечити різні конкретні реалізації під час виконання (тобто тестувати ресурси або макетні об'єкти)
  • Через вищезазначене, легко тестувати та рефакторировать

Якщо ви походите з інших мов, вам може бути знайома модель "Банда чотирьох". Кластери класів мають елементи як абстрактної фабрики, так і фасадів.

Публічна документація Apple досить широко охоплює кластери класів (і способи їх впровадження та розширення). На жаль, я виявив, що для багатьох розробників iOS ця та інші специфічні для какао моделі є сліпою зоною.

Основні компетенції какао: Кластер класів

Посібник з основ какао: Кластери класів

Приклади реалізації власних кластерів класів доступні на GitHub


7

Кластер класів NSArray не є "важким", це спосіб для використання будь-якої кількості реалізацій класу масиву, без того, щоб ваш код знав чи турбувався про конкретну реалізацію. Під капотом є конкретні підкласи NSArray, які підходять для різних випадків використання, такі як великі, розріджені масиви або масиви, що містять певну кількість елементів, відомих під час компіляції.

NSArray, NSString та NSNumber - це кластери класів, з якими ви найчастіше стикаєтесь.


6
Як не дивно, але на практиці вже використовується лише один конкретний клас для кластера - NSCF {Array | String | Number} - і зміни реалізації є внутрішніми для цього класу. Це, наскільки я знаю, у будь-якому випадку. Навіть екземпляри NSArray та NSMutableArray відображають один і той же клас.
Чак,

1
@Chuck - як це може бути так? Якби NSMutableArray та NSArray заявили, що є одним і тим же класом, не [myArray isKindOfClass:[NSMutableArray class]]повернули б ТАК, хоча це не повинно?
Роберт

1
@ Роберт: І справді так було на момент мого коментаря. Сьогодні Apple замінила NSCFArray на __NSArrayM та __NSArrayI, тому я думаю, що це вже не так, але я все одно не почуватимусь комфортно в залежності від цього, оскільки вони завжди можуть змінити його знову.
Чак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.