Czym dokładnie jest tak zwany „klaster klas” w celu C?

91

Czytałem, że NSArray jest właśnie taką rzeczą. Brzmi ciężko. Mam tutaj na biurku siedem naprawdę grubych książek o Objective-C, Cocoa i C. Żadna z nich w ogóle nie wspomina o Klastrze Klas, przynajmniej nie mogę jej znaleźć w Indeksie na końcu książek. Więc co to jest?

openfrog
źródło
Ups, następnym razem pomyślę o dodaniu linku do tego terminu. Gdybyś skomentował odpowiedź na poprzednie pytanie, odpowiedziałbym tam.
Georg Fritzsche
2
FWIW: niedawno (grudzień 2013 r.) Apple zalecił używanie klastrów klas jako sposobu na obsługę wstecznej kompatybilności z iOS 6 podczas korzystania z iOS 7. Było to na Apple Tech Talks 2013 / Berlin w sesji „Architecting Modern Apps, Part 2”. Apple zapowiedział, że będzie zamieszczał filmy z sesji wkrótce po ostatnim wydarzeniu (17 grudnia). Może to pomoże zrozumieć klastry klas w kontekście zmian w iOS 6/7.
brainray

Odpowiedzi:

42

Od docs Apple ... . Krótko mówiąc, jest to wzorzec projektowy używany we frameworku Foundation, dlatego prawdopodobnie nie ma o nim wzmianki w książkach ObjC.

Klaster klas to architektura, która grupuje szereg prywatnych, konkretnych podklas w publicznej, abstrakcyjnej nadklasie. Grupowanie klas w ten sposób zapewnia uproszczony interfejs użytkownikowi, który widzi tylko publicznie widoczną architekturę.

Echo
źródło
1
roflmao. dzięki. przejdę do Google następnym razem. Pomyślałem, że jeśli nie ma go w moich grubych książkach, może być tylko na twoich głowach;)
openfrog
1
Jedyną rzeczą, której brakuje w tym łączu, jest wyjaśnienie, jak najlepiej zmienić implementację ARC.
Hiperbola
193

Nie wiem, co jest w CDP, do którego odwoływał się Steve, ale w zasadzie klaster klasy Objective-C to konstrukcja, która obsługuje implementację abstrakcyjnego wzorca Factory .

Pomysł jest prosty : chcesz zapewnić Factory (Cluster) interfejs, który przy minimalnym opisem, produkuje i wraca konkretnej instancji beton Obiektu Fabryki że spełnia zachowanie rodziny klastra opisaną przez interfejs Factory (Cluster).

Prosty konkretny przykład : ten przykład przedstawia fabrykę śmiechu, która produkuje konkretne klasy określonych typów śmiechu (np. Guffaw, Giggle). Zwróć uwagę na metodę Laugh initWithLaughter:.

W Laugh.h:

#define kLaughWithGuffaw  1
#define kLaughWithGiggle  2

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

W 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.
źródło
24
Podczas gdy inne odpowiedzi były dobre, podając linki do dokumentów i książek, podoba mi się to, ponieważ sprawia, że ​​łatwo i przyjemnie jest zobaczyć, jak to zrobić. Dzięki
jamone
Ten przykład jest dobry, ale w typowym wzorcu Factory podklasy są publiczne. W klastrze klas podklasy są prywatne. developer.apple.com/library/ios/documentation/general/ ...
maxpower
1
@ AdriàNavarro Nie są one widoczne z zewnątrz, ponieważ zostały zadeklarowane w .m-file.
hfossli
4
(1) Jak bezpieczne jest uwolnienie siebie za pomocą initmetody i zwrócenie czegoś innego? Czy są jakieś przykłady kodu firmy Apple, w których to robią? (2) Ponadto prawdopodobnie tworzysz instancję z kodem takim jak [[Laugh alloc] initWithLaughter:kLaughWithGiggle]. Zwróć uwagę, jak Laughjest niepotrzebnie przydzielany, ponieważ zostanie zwolniony natychmiast po tym wywołaniu. Po co to robić, skoro można utworzyć metodę klasową, taką jak ta, [Laugh laughWithLaughter:kLaughWithGiggle]która zapewnia wszystkie zalety prywatnych podklas, unikając jednocześnie problemów 1 i 2 powyżej?
Senseful
1
@Senseful Masz rację. W rzeczywistości +alloczwraca pojedynczą klasę fabryki, która implementuje różne -initWith:metody. Metody klasy fabrycznej -initWith:są następnie odpowiedzialne za przydzielanie i inicjowanie konkretnej podklasy na podstawie podanych parametrów metody, jeśli jest to konieczne, lub w niektórych przypadkach mogą w ogóle niczego nie przydzielać (na przykład -[NSString initWithString:]). Można spróbować go poprzez kontrolę w wartości zwracanej +[NSString alloc], +[NSArray alloc]itp
Darren
25

Z programowania w celu c autorstwa Stephena Kochana na stronie 498 w glosariuszu, klaster:

Klasa abstrakcyjna, która grupuje zestaw prywatnych podklas konkretnych, zapewniając użytkownikowi uproszczony interfejs za pośrednictwem klasy abstrakcyjnej.

t011phr33
źródło
5
+1 Za cytowanie odpowiedzi z książki Objective-C, szczególnie biorąc pod uwagę pierwotne pytanie. To też dobra książka.
Quinn Taylor
(+1) za doskonałą rozdzielczość. Problem, który mam z nazywaniem tego wzorcem „Fabryka” polega na tym, że taka nazwa skupia się tylko na tworzeniu obiektów, a nie na ukrytych interakcjach prywatnych podklas zarządzanych przez abstrakcyjną nadklasę. Rzeczywiście, nawet nazwanie tej nadklasy „abstrakcyjną” może być mylące, ponieważ w rzeczywistości jest ona całkowicie (wewnętrznie) zależna od swoich własnych podklas, a zatem nie jest zwykłą klasą abstrakcyjną, która generalnie nie wie nic o swoich podklasach.
devios1
18

Klastry klas zapewniają pojedynczy interfejs publiczny dla grupy konkretnych, prywatnych implementacji podklas. Programista z celem-c często używa klastrów klas i rzadko zdaje sobie z tego sprawę - i o to właśnie chodzi w klastrze klas. Zadaniem klastra klas jest ukrycie złożoności szczegółów implementacji za publicznym interfejsem.

Wiele klas Foundation to klastry klas, takie jak NSString, NSArray, NSDictionary i NSNumber. Kiedy wywołujesz [NSString stringWithFormat:]klasę, klaster udostępnia konkretną klasę, która implementuje NSStringinterfejs. To może być NSConcreteString, NSCFString, NSFooBarString, itd. Które klaster klasa daje bazuje na konstruktora lub inicjator dzwonisz i argumenty.

Z tego powodu klastry klas są jedną z najbardziej inspirujących koncepcji programowania w języku Objective-C.

  • Bardzo łatwe do wdrożenia
  • Łatwo zmienić podstawową implementację bez zmiany kodu, który ją wywołuje.
  • Łatwe udostępnianie różnych konkretnych implementacji w czasie wykonywania (np. Testowanie zasobów lub pozorowane obiekty)
  • Z tego powodu jest łatwy do przetestowania i refaktoryzacji

Jeśli pochodzisz z innych języków, być może znasz wzorce Gang of Four. Klastry klas zawierają elementy zarówno abstrakcyjnej fabryki, jak i wzorów elewacji.

Publiczna dokumentacja firmy Apple dość obszernie obejmuje klastry klas (oraz sposoby ich implementacji i rozszerzania). Niestety odkryłem, że dla wielu programistów iOS ten i inne wzorce specyficzne dla Cocoa są martwym punktem.

Podstawowe kompetencje kakao: Klaster klas

Przewodnik po podstawach kakao: Klastry klas

Przykłady sposobów implementacji własnych klastrów klas są dostępne w witrynie GitHub

quellish
źródło
7

Klaster klas NSArray nie jest „ciężki”, jest sposobem na użycie dowolnej liczby implementacji klasy tablicowej bez wiedzy Twojego kodu lub dbania o nią. Pod maską znajdują się konkretne podklasy NSArray, które są odpowiednie dla różnych przypadków użycia, takich jak duże, rzadkie tablice lub tablice zawierające określoną liczbę elementów, które są znane w czasie kompilacji.

NSArray, NSString i NSNumber to najczęściej spotykane klastry klas.

NSResponder
źródło
6
Jak na ironię, w praktyce tylko jedna konkretna klasa na klaster jest już używana - NSCF {Array | String | Number} - a zmiany implementacji są wewnętrzne dla tej klasy. W każdym razie, o ile wiem. Nawet instancje NSArray i NSMutableArray pokazują tę samą klasę.
Chuck
1
@Chuck - jak to możliwe? Jeśli NSMutableArray i NSArray zgłosiły, że są tą samą klasą, nie [myArray isKindOfClass:[NSMutableArray class]]zwróciłyby TAK, nawet jeśli nie powinno?
Robert
1
@Robert: I rzeczywiście tak było w momencie mojego komentarza. Obecnie Apple zastąpiło NSCFArray __NSArrayM i __NSArrayI, więc myślę, że już tak nie jest, ale nadal nie czułbym się komfortowo, polegając na tym, ponieważ zawsze mogliby to zmienić ponownie.
Chuck