Что такое так называемый «кластер классов» в Objective-C?


91

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


Ой, в следующий раз я подумаю добавить ссылку на этот термин. Если бы вы прокомментировали ответ на предыдущий вопрос, я бы ответил там.
Георг Фриче,

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

Ответы:


42

Из документации Apple, ... . Короче говоря, это шаблон проектирования, используемый во фреймворке Foundation, и, вероятно, поэтому он не упоминается в книгах по ObjC.

Кластер классов - это архитектура, которая объединяет несколько частных конкретных подклассов в общий абстрактный суперкласс. Группировка классов таким образом обеспечивает упрощенный интерфейс для пользователя, который видит только общедоступную архитектуру.


1
roflmao. Спасибо. собираюсь погуглить в следующий раз. подумал, что если этого нет в моих толстых книгах, это может быть только на вашей голове;)
openfrog

1
Единственное, чего не хватает в этой ссылке, так это объяснения того, как лучше всего изменить реализацию ARC.
Hyperbole

193

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

Идея проста : Вы хотите , чтобы обеспечить завод (кластер) интерфейс, с минимальным описанием, производит и возвращают определенный конкретный экземпляр объекта Factory , который удовлетворяет поведение семейства кластеров , описанное интерфейс Factory (Cluster).

Простой конкретный пример : этот пример предоставляет фабрику смеха, которая производит конкретные классы определенных типов смеха (например, 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 09

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

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

25

Из программирования в цели c Стивена Кочана на странице 498 в глоссарии, кластер:

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


5
+1 За цитирование ответа из книги Objective-C, особенно учитывая исходный вопрос. Это тоже хорошая книга.
Куинн Тейлор

(+1) за отличное определение. Проблема с тем, что я называю это шаблоном «Фабрика», заключается в том, что такое имя фокусируется только на создании объектов, а не на внутренних взаимодействиях частных подклассов, управляемых абстрактным суперклассом. В самом деле, даже называть этот суперкласс «абстрактным» может вводить в заблуждение, поскольку он фактически (внутренне) зависит от своих собственных подклассов и, следовательно, не является обычным абстрактным классом, который обычно ничего не знает о своих подклассах.
devios1 08

18

Кластеры классов предоставляют единый открытый интерфейс для группы конкретных частных реализаций подклассов. Программист на Objective-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
@ Чак - как это может быть? Если NSMutableArray и NSArray заявили, что принадлежат к одному классу, не [myArray isKindOfClass:[NSMutableArray class]]вернет YES, даже если не должно?
Роберт

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