Objective-C Bileşik Nesneleri

İçerisine bir nesne yerleştiren bir sınıfı tanımlayan bir sınıf kümesi içinde alt sınıf oluşturabiliriz. Bu sınıf nesneleri kompozit nesnelerdir. Dolayısıyla, sınıf kümesinin ne olduğunu merak ediyor olabilirsiniz. Bu yüzden önce sınıf kümesinin ne olduğunu göreceğiz.

Sınıf Kümeleri

Sınıf kümeleri, temel çerçevesinin yaygın olarak kullandığı bir tasarım modelidir. Sınıf kümeleri, kamuya açık bir soyut üst sınıf altında bir dizi özel somut alt sınıfı gruplandırır. Sınıfların bu şekilde gruplandırılması, işlevsel zenginliğini azaltmadan nesne yönelimli bir çerçevenin halka açık mimarisini basitleştirir. Sınıf kümeleri,abstract factory tasarım deseni.

Basitleştirmek için, benzer işlevler için birden çok sınıf oluşturmak yerine, girdinin değerine göre işlenmesiyle ilgilenecek tek bir sınıf oluşturuyoruz.

Örneğin, NSNumber'da char, int, bool vb. Gibi birçok sınıf kümemiz var. Hepsini tek bir sınıfta benzer işlemlerle ilgilenen tek bir sınıfta gruplandırıyoruz. NSNumber aslında bu ilkel türlerin değerini nesnelere sarar.

Bileşik Nesne nedir?

Kendi tasarımımız olan bir nesneye özel bir küme nesnesi yerleştirerek, bileşik bir nesne oluşturuyoruz. Bu bileşik nesne, temel işlevselliği için küme nesnesine güvenebilir, yalnızca bileşik nesnenin belirli bir şekilde işlemek istediği mesajları yakalar. Bu mimari, yazmamız gereken kod miktarını azaltır ve Foundation Framework tarafından sağlanan test edilmiş koddan yararlanmanızı sağlar.

Bu, aşağıdaki şekilde açıklanmaktadır.

Bileşik nesne, kendisini kümenin soyut üst sınıfının bir alt sınıfı olarak bildirmelidir. Bir alt sınıf olarak, üst sınıfın ilkel yöntemlerini geçersiz kılmalıdır. Ayrıca türetilmiş yöntemleri geçersiz kılabilir, ancak bu gerekli değildir çünkü türetilmiş yöntemler ilkel yöntemler aracılığıyla çalışır.

NSArray sınıfının count yöntemi bir örnektir; araya giren nesnenin geçersiz kıldığı bir yöntemi uygulaması şu kadar basit olabilir:

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

Yukarıdaki örnekte, gömülü nesne aslında NSArray tipindedir.

Bir Bileşik Nesne Örneği

Şimdi eksiksiz bir örnek görmek için aşağıda verilen Apple belgelerinden örneğe bakalım.

#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;
}

Şimdi programı derleyip çalıştırdığımızda aşağıdaki sonucu alacağız.

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

Yukarıdaki örnekte, dizinin bir işlevini doğrulamanın, normal senaryoda çökmeye neden olacak boş nesnelerin eklenmesine izin vermeyeceğini görebiliriz. Ancak doğrulama dizimiz bununla ilgileniyor. Benzer şekilde, doğrulama dizisindeki her yöntem, normal işlem dizisinden ayrı olarak doğrulama süreçleri ekler.