In my post on preferring composition to inheritance, I talked about the powers of the Decorator Pattern for adding behavior to something that already exists. Really, the decorator pattern is a lot like inheritance, just better in almost every way:

Instead of calling super when you need to access the parent, you use self.wrappedThing.

You get to explicitly disallow which messages get through to the wrapped object, instead of them all magically getting through to the superclass. This is a bit more work, especially if you have a lot of messages, but “explicit is better than implicit”, as PEP 20 says.

With subclassing, each subclass is locked to one superclass. With decoration, you can inject anything, since you just pass it in to the initializer. This makes testing way easier, since you can wrap anything, including a mock.

With subclassing, you have to decide at instantiation time which class you want to use and which behavior you want to add. With decoration, you can wrap the object with new behavior at your leisure, even wrapping one object in two different ways to add different behaviors to the same object.

You can decorate a decorated object, and you can continue to nest as many times as you want. At run-time, you can decide if you want to leave any levels of this nesting chain out.

And that nesting is what I want to talk about this week. They’re a lot like Matryoshka dolls. One goes into the next, over and over. But software is weird, so you can nest something that is the exact same “size” as the last thing. In the physical world, each nesting object has to get bigger than the last one. But in the digital world, the footprint of each object (namely, its type) doesn’t have to get bigger when it wraps something. What do I mean?

Let’s take a look at an example from Yegor Bugayenko’s blog. He has an interface (just an @protocol in Java-land):

interface Text {  
	String read();  
}  

And he creates a chain of nested decorators to add a bunch of behavior to a core object:

final Text text = new AllCapsText(  
	new TrimmedText(  
		new PrintableText(  
			new TextInFile(new File("/tmp/a.txt"))  
		)  
	)  
);  
String content = text.read();  

That core object is the text from a file, and, crucially, he’s able to add all that stuff without increasing the footprint of each nested object beyond the Text interface that he defined above. The added benefit here is that you don’t have to expose a bunch of methods on each layer. Just conform to the protocol, and you’re good to go.

I adopted this pattern for Instant Cocoa’s data sources. Data sources in Instant Cocoa represent a collection where elements are fetched with index paths. You can browse the code for Instant Data Source. Here’s a truncated version of the ICDataSource protocol.

@protocol ICDataSource

//...

@property (nonatomic, assign, readonly) NSUInteger numberOfSections;  
- (NSUInteger)numberOfObjectsInSection:(NSUInteger)section;  
- (id)objectAtIndexPath:(NSIndexPath *)indexPath;

//...

@end  

From this protocol, we derive several concrete implementations. First, ICSimpleDataSource, which is initialized with an array and represents a data source with one section. We also have ICRemoteDataSource and ICPaginatedDataSource, which are capable of asynchronously fetching a remote collection of objects, mapping them to your domain, and presenting them as a data source. These data sources are simple and straightforward.

Where ICDataSource objects get interesting is how you can nest them. ICSectionedDataSource is initialized with an ICDataSource, and uses its contents (along with a sectioningKey ) to present a new data source, with a section for each unique value of the sectioningKey. Because it takes a data source instead of a plain array, you can use either ICSimpleDataSource or ICRemoteDataSource (or any data source of your own choosing, such as one that is initialized with an NSFetchRequest and fetches Core Data objects).

Another example of nested data sources is ICMultiDataSource. ICMultiDataSource is initialized with an array of data sources, and each sub-data-source it holds becomes its own section. (There’s an option to preserve subsections.) Again, since everything is built on this one protocol, we can wrap any combination of other data sources, including any of the ones previously mentioned, or, of course, your own custom ones. And again, its type “footprint” is still only ICDataSource, no matter what sub-data-sources it’s composed of.

You could also imagine something like an SKShowMoreDataSource, which would present the first, say, 3 objects, and then an object that is a placeholder for a cell that says “Show more…”. When the user taps on that cell, you could extract the full data source and pass it to a new table view controller that would present the full list.

In its original conception, ICPaginatedDataSource was a subclass of ICRemoteDataSource, which was a subclass of ICSectionedDataSource, which was a subclass of ICSimpleDataSource. This architecture was so limiting: since the “footprint” of each object included the footprint of all the classes above, it was hard to test all the various options and configurations. Now, you can inject any custom data source you want at any level, and the provided utility classes will use them correctly. Since they now all present the same interface and only the behavior changes, testing them is easier and they’re far more flexible.