O que exatamente é o chamado “Cluster de Classes” em Objective-C?

91

Eu estava lendo que NSArray é exatamente isso. Parece pesado. Eu tenho 7 livros bem gordos aqui na minha mesa sobre Objective-C, Cocoa e C. Nenhum deles menciona Class Cluster, pelo menos não consigo encontrar no Index no final dos livros. Então o que é isso?

rã aberta
fonte
Opa, da próxima vez, pensarei em adicionar um link para esse termo. Se você tivesse comentado a resposta à sua pergunta anterior, eu teria respondido lá.
Georg Fritzsche
2
FWIW: recentemente (dezembro de 2013) a Apple recomendou o uso de Class Clusters como uma forma de lidar com a compatibilidade com versões anteriores do iOS 6 durante o uso do iOS 7. Isso foi no Apple Tech Talks 2013 / Berlin na sessão "Architecting Modern Apps, Part 2". A Apple informou que postará vídeos das sessões logo após o último evento (17 de dezembro). Então, talvez isso ajude a entender os Class Clusters dentro do contexto real das mudanças do iOS 6/7.
brainray

Respostas:

42

De docs da Apple ... . Resumindo, é um padrão de design usado na estrutura da Fundação, provavelmente por isso não é mencionado nos livros ObjC.

Um cluster de classe é uma arquitetura que agrupa várias subclasses concretas e privadas em uma superclasse abstrata e pública. O agrupamento de classes dessa forma fornece uma interface simplificada para o usuário, que vê apenas a arquitetura visível publicamente.

eco
fonte
1
roflmao. obrigado. vou ao google na próxima vez. pensei que se não estiver em meus livros gordos, só pode estar em suas cabeças;)
openfrog
1
O que falta neste link é uma explicação sobre a melhor forma de alterar a implementação do ARC.
Hipérbole de
193

Não sei o que há no CDP que Steve fez referência, mas basicamente o Objective-C Class Cluster é uma construção que dá suporte à implementação do padrão Factory abstrato .

A ideia é simples : você deseja fornecer uma interface Factory (Cluster) que, com uma descrição mínima, fabrique e retorne uma instância concreta específica de um Factory Object que satisfaça o comportamento da família de cluster descrita pela interface Factory (Cluster).

Um exemplo concreto simples : Este exemplo fornece uma fábrica de risos que produz classes concretas de tipos específicos de risos (por exemplo, Guffaw, Giggle). Preste atenção ao método Laugh initWithLaughter : .

Em Laugh.h:

#define kLaughWithGuffaw  1
#define kLaughWithGiggle  2

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

Em 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
Frank C.
fonte
24
Embora as outras respostas tenham sido boas ao fornecer links para documentos e livros, eu gosto disso porque torna simples e agradável ver como fazer isso de fato. Obrigado
jamone
Este exemplo é bom, mas em um padrão Factory típico, as subclasses são públicas. Em um cluster de classes, as subclasses são privadas. developer.apple.com/library/ios/documentation/general/…
maxpower
1
@ AdriàNavarro Não são visíveis para o exterior porque estão declarados no .m-file.
hfossli
4
(1) Quão seguro é liberar-se em um initmétodo e retornar outra coisa? Existe algum exemplo de código da Apple onde eles fazem isso? (2) Além disso, você provavelmente está criando uma instância com código como [[Laugh alloc] initWithLaughter:kLaughWithGiggle]. Observe como Laughestá sendo alocado desnecessariamente, pois será liberado imediatamente após esta chamada. Por que fazer isso quando você pode criar um método de classe como o [Laugh laughWithLaughter:kLaughWithGiggle]que oferece todas as vantagens das subclasses privadas, enquanto evita os problemas 1 e 2 acima?
Senseful
1
@Senseful Você está certo. Na vida real, +allocretorna uma classe de fábrica de singleton que implementa os vários -initWith:métodos. Os -initWith:métodos da classe de fábrica são então responsáveis ​​por alocar e inicializar uma subclasse concreta com base nos parâmetros do método dado, se necessário, ou em alguns casos podem não alocar nada (como-[NSString initWithString:] ). Você pode experimentá-lo pela inspeção no valor de retorno +[NSString alloc], +[NSArray alloc]etc.
Darren
25

Da programação no objetivo c por Stephen Kochan na página 498 no glossário, agrupe:

Uma classe abstrata que agrupa um conjunto de subclasses concretas privadas, fornecendo uma interface simplificada ao usuário por meio da classe abstrata.

t011phr33
fonte
5
+1 Por citar uma resposta de um livro Objective-C, especialmente dada a pergunta original. É um bom livro também.
Quinn Taylor
(+1) pela excelente definição. O problema que tenho em chamar isso de padrão "Fábrica" ​​é que esse nome se concentra apenas na criação de objetos, não nas interações subjacentes das subclasses privadas gerenciadas pela superclasse abstrata. Na verdade, mesmo chamar essa superclasse de "abstrata" pode ser enganoso, pois ela é na verdade bastante (internamente) dependente de suas próprias subclasses e, portanto, não é uma classe abstrata normal que geralmente não sabe nada sobre suas subclasses.
devios1
18

Os clusters de classes fornecem uma única interface pública para um grupo de implementações concretas de subclasses privadas. Um programador objetivo-c usa clusters de classes com frequência e raramente percebe isso - e esse é o ponto principal de um cluster de classes. O trabalho de um cluster de classe é ocultar a complexidade dos detalhes de implementação por trás de uma interface pública.

Muitas das classes Foundation são clusters de classe, como NSString, NSArray, NSDictionary e NSNumber. Quando você chama [NSString stringWithFormat:]a classe cluster está dando a você alguma classe concreta que implementa a NSStringinterface. Poderia ser um NSConcreteString, NSCFString,NSFooBarString , etc. Qual o cluster classe dá-lhe é baseado no construtor ou initializer você está chamando e os argumentos.

Por causa disso, os clusters de classe são um dos conceitos mais poderosos na programação Objective-C.

  • Muito fácil de implementar
  • Fácil de alterar a implementação subjacente sem alterar o código que a chama.
  • Fácil de fornecer diferentes implementações concretas em tempo de execução (ou seja, recursos de teste ou objetos simulados)
  • Por causa do acima, fácil de testar e refatorar

Se você está vindo de outras línguas, pode estar familiarizado com os padrões da Gangue dos Quatro. Os clusters de classes têm elementos tanto da fábrica abstrata quanto dos padrões de fachada.

A documentação pública da Apple cobre clusters de classes (e como implementá-los e estendê-los) de forma bastante extensa. Infelizmente, descobri que, para muitos desenvolvedores de iOS, esse e outros padrões específicos do Cocoa são um ponto cego.

Competências essenciais do cacau: grupo de classes

Cocoa Fundamentals Guide: Class Clusters

Exemplos de como implementar seus próprios clusters de classe estão disponíveis no GitHub

abafado
fonte
7

O cluster da classe NSArray não é "pesado", é uma maneira de qualquer número de implementações de uma classe de array ser usado sem que seu código saiba ou se importe com a implementação específica. Sob o capô, existem subclasses concretas de NSArray que são apropriadas para diferentes casos de uso, como matrizes grandes e esparsas ou matrizes contendo um número específico de elementos que são conhecidos em tempo de compilação.

NSArray, NSString e NSNumber são os clusters de classe que você encontrará com mais frequência.

NSResponder
fonte
6
Ironicamente, na prática, apenas uma classe concreta por cluster é usada mais - NSCF {Array | String | Number} - e as mudanças de implementação são internas a essa classe. Pelo menos isso é o que eu sei. Mesmo as instâncias NSArray e NSMutableArray mostram a mesma classe.
Chuck
1
@Chuck - como pode ser esse o caso? Se um NSMutableArray e NSArray relatassem ser a mesma classe não [myArray isKindOfClass:[NSMutableArray class]]retornariam SIM, embora não devesse?
Robert
1
@Robert: E de fato era esse o caso na hora do meu comentário. Hoje em dia a Apple substituiu NSCFArray por __NSArrayM e __NSArrayI, então acho que não é mais assim, mas ainda não me sentiria confortável dependendo disso, pois eles sempre poderiam alterá-lo novamente.
Chuck