Objective-C Design Patterns
- Working Around the Language
- The Art of Delegation
- A Faade of Respectability
- Models and Views
- Targets and Actions
- Higher Order Messaging
- Summary
Design patterns are based on the ideas of Christopher Alexander, who proposed pattern languages for expressing reused concepts in architecture. In the 1980s, the concept was adopted be programmers and, although it lost a lot of the original ideas in the translation, became a popular tool for designing software.
Design patterns are reusable ideas at a higher level of abstraction than the code. They make it easy to read and talk about code. Rather than having to understand exactly what the code is doing, you just need to know that it's an implementation of a particular pattern, and then the only thing that you need to understand is what makes this particular implementation different from others.
Working Around the Language
Critics of design patterns claim that they only exist to work around limitations in the language. This is a particularly common view among Lisp programmers, who use a language that can implement most of the patterns from the Gang of Four's book in reusable macros.
With this in mind, it's worth looking first at the patterns that you won't use in Objective-C. The most obvious example is the command pattern. The idea behind the command pattern is to provide some higher level of abstraction over function calls or method invocations that let the callee do something before the real implementation. A common use might be recording the commands for creating an undo history.
In Objective-C, you don't need this pattern because every message send provides the same advantages. If your object doesn't respond to a given message, you can implement -forwardInvocation: and handle the message using some custom code. If you need to do any pre- or post-processing, then you can implement this method in a proxy.
Another example is the factory pattern. With this pattern, you have one object that is responsible for creating instances of another. In Objective-C (and Smalltalk), this role is filled by classes. Classes in Objective-C, unlike C++ and other Simula-like languages, are first-class objects. They are responsible for creation of their instances.
In C++ or Java, you have a new keyword that creates an instance of a named class. In Objective-C, you send the class a message and it returns an instance. Whether the instance is of that class, a subclass, or some unrelated class, and whether it is new or recycled are policy decisions that the class makes.
A common way in which this is used is the implementation of class clusters. A number of the standard Cocoa classes are really class clusters. When you create an instance of one, you are really getting an instance of a subclass. Exactly which subclass you get depends on how you initialized the object. NSArray is a good example of this. It may be implemented by a simple C array, a linked list, or some other data structure optimized for the data you store in it. The same is true of NSDictionary. If you subclass either of these, you are required to implement the small number of primitive methods that the superclass uses to implement all of the more complex functionality.