A class cluster is an architecture that groups a number of private, concrete subclasses under a public, abstract superclass. The grouping of classes in this way provides a simplified interface to the user, who sees only the publicly visible architecture. Behind the scenes, though, the abstract class is calling up the private subclass most suited for performing a particular task. For example, several of the common Cocoa classes are implemented as class clusters, including
NSDictionary. There are many ways in which they can represent their internal data storage. For any particular instance, the abstract class chooses the most efficient class to use based on the data that instance is being initialized with.
You create and interact with instances of the cluster just as you would any other class. Behind the scenes, though, when you create an instance of the public class, the class returns an object of the appropriate subclass based on the creation method that you invoke. (You don’t, and can’t, choose the actual class of the instance.)
Taking the Foundation framework’s
NSString class as an example, you could create three different string objects:
NSString *string1 = @"UTF32.txt";
NSString *string2 = [NSHomeDirectory() stringByAppendingPathComponent:string1];
NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string2];
NSString *string3 = [storage string];
Each string may be an instance of a different private subclass (and in fact, on OS X v10.5, each is). Although each of the objects is of a private subclass of
NSString, it’s convenient to consider each of the objects to be instances of the
NSString class. You use the instance methods declared by
NSString just as you would if they were instances of
The benefit of a class cluster is primarily efficiency. The internal representation of the data that an instance manages can be tailored to the way it’s created or being used. Moreover, the code you write will continue to work even if the underlying implementation changes.
The class cluster architecture involves a trade-off between simplicity and extensibility: Having a few public classes stand in for a multitude of private ones makes it easier to learn and use the classes in a framework but somewhat harder to create subclasses within any of the clusters.
A new class that you create within a class cluster must:
Be a subclass of the cluster’s abstract superclass
Declare its own storage
Override the superclass’s primitive methods
If it’s rarely necessary to create a subclass—as is the case with class clusters in the Foundation framework—then the cluster architecture is clearly beneficial. You might also be able to avoid subclassing by using composition; by embedding a private cluster object in an object of your own design, you create a composite object. This composite object can rely on the cluster object for its basic functionality, only intercepting messages that it wants to handle in some particular way. Using this approach reduces the amount of code you must write and lets you take advantage of the tested code provided by the Foundation Framework.