Design Patterns in Objective-C
I’ve already done a post on design patterns which I used within the Triply App, however I’ve started to explore some of the other recognised design patterns used throughout software development in order to hopefully expand my knowledge and better help with solving design problems using tried and tested solutions. If you haven’t already, you should read the ‘gang of four’, Design Patterns – Elements of reusable object-orientated software book. I found that rather than reading the book cover to cover and trying to memorise the content, it was better to read the first section that explains at a high level what each of the design patterns are and then to go away and research how these can be applied within Objective-C and iOS development. This is mainly because the book was originally written over 20 years ago and although the patterns still apply today, the examples use to bring them to life are now outdated and the code used to present them is C++ and Smalltalk. You’ll also find some patterns are implemented differently using Objective-C as a result of for example the lack of multiple inheritance or the addition of things like categories. I’ve done a quick summary of a few of the patterns and how they’re used within Objective-C.
Prototype The prototype pattern can be used when you potentially need to create a number of similar objects that are expensive to initialise. The idea is that these objects know how to ‘clone’ themselves, then upon creation of the first one, you hand it off to a ‘prototype manager’ class which stores it within a dictionary for a particular key. Then the next time you need one, rather than creating it from scratch you ask the prototype manager for one using the key you specified, it pulls the object out, calls ‘clone’ on it and hands you back the copy. Providing the initialisation would have been more expensive that the ‘clone’ method, this procedure is potentially much faster.
Adapter Usually this pattern involves creating a third class ‘C’ which allows incompatible classes ‘A’ and ‘B’ to work together. However in Objective-C this is implemented using categories. If class ‘A’ needs specific methods on class ‘B’ which class ‘B’ doesn’t provide, instead of creating a third class as a ‘go between’, you define a category on class ‘B’ right within class ‘A’s implementation file. Class ‘B’ doesn’t even need to know about this methods which is good in terms of decoupling as they are only intended for class ‘A’ to do it’s job.
Composite The composite pattern is used when building/representing tree structures and wanting to refer to the ‘nodes’ using a common interface, whether they be parents or ‘leaf’ nodes. You start with a common base class that both parent and leaf nodes subclass. The leaf nodes generally only override the ‘operation’ method, which performs the task of that object, for example ‘draw’. The parent nodes contain storage for their children (ie. An array) and also implement the ‘operation’ method buy looping through it’s children and calling their ‘operation’ method. This allows the client to to invoke the desired functionality regardless of which node within the tree they are dealing with. For a more detailed explanation - http://java.dzone.com/articles/design-patterns-composite
Facade The façade pattern is used to simplify and consolidate a number of interfaces into a single interface, essentially making it easier for the client to communicate with the system. Say for example you need to perform an operation that involves a number of different classes, you could create an object (facade)that encapsulates all of these classes and provides a single method for performing that operation. Façade can also be used if say you have a number of ‘manager’ type classes, you could create a class that can be used as a single entry point for all of these classes to save dealing with the managers individually.
Flyweight Flyweight is similar to the prototype pattern in that it uses a manager to store objects into a collection for reuse however there’s a subtle difference. The prototype pattern is a creational patten as it creates a new object by cloning the existing one in the collection and passing it back whereas the flyweight pattern passes you a pointer to the existing object in the collection. At this point you apply extrinsic data such as where the object should draw itself and then call it’s operation, i.e. Draw(). Flyweight allows for a reduction in the number of similar objects you need to use within your application by reusing previously created objects that have the same intrinsic data.
Proxy The proxy pattern is simply a way of representing an object using a separate class, within which you can you add additional requirements/functionality or checks to the object being represented. For example you have an interface that might define a method called moveCar(). You’d then have two classes which implement this interface, one which is a proxy object and one which is the real object. When the client calls moveCar() the method within the proxy object is called which in turn calls moveCar() in the real object. It’s here within the proxy object you can add any additional checks before calling the method in the real object, for example if (driver.age > 17). Another reason for doing this may be to defer the cost of the real objects creation until the client actually needs to use it.