Objetos compostos Objective-C

Podemos criar uma subclasse dentro de um cluster de classe que define uma classe que incorpora dentro dela um objeto. Esses objetos de classe são objetos compostos. Então você deve estar se perguntando o que é um cluster de classe. Portanto, veremos primeiro o que é um cluster de classe.

Clusters de classe

Os clusters de classes são um padrão de design que a estrutura de base faz uso extensivo. Os clusters de classes agrupam várias subclasses concretas privadas sob uma superclasse pública abstrata. O agrupamento de classes desta forma simplifica a arquitetura publicamente visível de uma estrutura orientada a objetos sem reduzir sua riqueza funcional. Os clusters de classes são baseados noabstract factory padrão de design.

Para simplificar, em vez de criar várias classes para funções semelhantes, criamos uma única classe que cuidará de seu tratamento com base no valor de entrada.

Por exemplo, em NSNumber temos muitos clusters de classes como char, int, bool e assim por diante. Nós agrupamos todos eles em uma única classe que se encarrega de lidar com operações semelhantes em uma única classe. NSNumber, na verdade, envolve o valor desses tipos primitivos em objetos.

O que é um objeto composto?

Incorporando um objeto de cluster privado em um objeto de nosso próprio projeto, criamos um objeto composto. Este objeto de composição pode contar com o objeto de cluster para sua funcionalidade básica, apenas interceptando mensagens que o objeto de composição deseja tratar de alguma maneira particular. Essa arquitetura reduz a quantidade de código que devemos escrever e permite que você aproveite as vantagens do código testado fornecido pelo Foundation Framework.

Isso é explicado na figura a seguir.

O objeto de composição deve se declarar uma subclasse da superclasse abstrata do cluster. Como uma subclasse, ele deve substituir os métodos primitivos da superclasse. Ele também pode substituir métodos derivados, mas isso não é necessário porque os métodos derivados funcionam por meio dos primitivos.

O método de contagem da classe NSArray é um exemplo; a implementação do objeto interveniente de um método que ele substitui pode ser tão simples quanto -

- (unsigned)count  {
   return [embeddedObject count];
}

No exemplo acima, o objeto incorporado é, na verdade, do tipo NSArray.

Um exemplo de objeto composto

Agora, para ver um exemplo completo, vejamos o exemplo da documentação da Apple que é fornecido abaixo.

#import <Foundation/Foundation.h>

@interface ValidatingArray : NSMutableArray {
   NSMutableArray *embeddedArray;
}

+ validatingArray;
- init;
- (unsigned)count;
- objectAtIndex:(unsigned)index;
- (void)addObject:object;
- (void)replaceObjectAtIndex:(unsigned)index withObject:object;
- (void)removeLastObject;
- (void)insertObject:object atIndex:(unsigned)index;
- (void)removeObjectAtIndex:(unsigned)index;

@end

@implementation ValidatingArray
- init {
   self = [super init];
   if (self) {
      embeddedArray = [[NSMutableArray allocWithZone:[self zone]] init];
   }
   return self;
}

+ validatingArray {
   return [[self alloc] init] ;
}

- (unsigned)count {
   return [embeddedArray count];
}

- objectAtIndex:(unsigned)index {
   return [embeddedArray objectAtIndex:index];
}

- (void)addObject:(id)object {
   if (object != nil) {
      [embeddedArray addObject:object];
   }
}

- (void)replaceObjectAtIndex:(unsigned)index withObject:(id)object; {
   if (index <[embeddedArray count] && object != nil) {
      [embeddedArray replaceObjectAtIndex:index withObject:object];
   }
}

- (void)removeLastObject; {
   if ([embeddedArray count] > 0) {
      [embeddedArray removeLastObject];
   }
}

- (void)insertObject:(id)object atIndex:(unsigned)index; {
   if (object != nil) {
      [embeddedArray insertObject:object atIndex:index];
   }
}

- (void)removeObjectAtIndex:(unsigned)index; {
   if (index <[embeddedArray count]) {
      [embeddedArray removeObjectAtIndex:index];
   }
}

@end

int main() {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   ValidatingArray *validatingArray = [ValidatingArray validatingArray];
   
   [validatingArray addObject:@"Object1"];
   [validatingArray addObject:@"Object2"];
   [validatingArray addObject:[NSNull null]];
   [validatingArray removeObjectAtIndex:2];
   NSString *aString = [validatingArray objectAtIndex:1];
   NSLog(@"The value at Index 1 is %@",aString);
   [pool drain];
   
   return 0;
}

Agora, quando compilarmos e executarmos o programa, obteremos o seguinte resultado.

2013-09-28 22:03:54.294 demo[6247] The value at Index 1 is Object2

No exemplo acima, podemos ver que validar a função única do array não permitiria adicionar objetos nulos que levariam a um travamento no cenário normal. Mas nosso array de validação cuida disso. Da mesma forma, cada um dos métodos de validação de array adiciona processos de validação além da sequência normal de operações.