Design Patterns on iOS
Design Patterns iOS
Adapter, Chain of responsibility, Decorator, Facade
In this article, i am going to cover four design patterns which you can relate with your current project and its easy to understand with examples like how cocoa adapts those patterns. Let’s start with adapter..
1. Adapter
The Adapter design pattern converts the interface of a class into another interface that clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces. It decouples the client from the class of the targeted object.
How Cocoa adapts Adapter Design Patterns?
Protocols
A protocol is a language-level (Objective-C) feature that makes it possible to define interfaces that are instances of the Adapter pattern. A protocol is essentially a series of method declarations unassociated with a class. (In Java, interface is synonymous with protocol.) If you want a client object to communicate with another object, but the objects’ incompatible interfaces make that difficult, you can define a protocol. The class of the other object then formally adopts the protocol and “conforms” to it by implementing one or more of the methods of the protocol. The protocol may require the conforming class to implement some of its methods and may leave the implementation of others optional. The client object can then send messages to the other object through the protocol interface.
Note: Design of protocols does not perfectly match the description of the Adapter pattern. But it achieves the goal of the pattern: allowing classes with otherwise incompatible interfaces to work together.
Uses and Limitations
For example, the Foundation framework includes the
NSObject
,
NSCopying
, and
NSCoding
protocols, which are all very important ones. AppKit protocols
include
NSDraggingInfo
,
NSTextInput
, and
NSChangeSpelling
. UIKit protocols include
UITextInputTraits
,
UIWebViewDelegate
, and
UITableViewDataSource
.
2. Chain of Responsibility
The Chain of Responsibility design pattern decouples the sender of a request from its receiver by giving more than one object a chance to handle the request. The pattern chains the receiving objects together and passes the request along the chain until an object handles it. Each object in the chain either handles the request or passes it to the next object in the chain.
How Cocoa adapts Chain of Responsibility Design Patterns?
Responder Chain
The application frameworks include an architecture known as the
responder chain. This chain consists of a series of responder
objects (that is, objects inheriting from
NSResponder
or, in UIKit,
UIResponder
) along which an event (for example, a mouse click) or action
message is passed and (usually) eventually handled. If a given
responder object doesn’t handle a particular message, it passes
the message to the next responder in the chain. The order of
responder objects in the chain is generally determined by the
view hierarchy, with the progression from lower-level to
higher-level responders in the hierarchy, culminating in the
window object that manages the view hierarchy, the delegate of
the window object, or the global application object. The paths
of events and action messages up the responder chain is
different. An application can have as many responder chains as
it has windows (or even local hierarchies of views); but only
one responder chain can be active at a time—the one associated
with the currently active window.
Note: The design of the view hierarchy, which is closely related to the responder chain, adapts the Composite pattern.
Uses and Limitations
When you construct a user interface for a program either by
using Interface Builder or programmatically, you get one or more
responder chains “for free.” The responder chain goes hand in
hand with a view hierarchy, which you get automatically when you
make a view object a subview of a window’s content view. If you
have a custom view added to a view hierarchy, it becomes part of
the responder chain. If you implement the appropriate
NSResponder
or
UIResponder
methods, you can receive and handle events and action messages.
A custom object that is a delegate of a window object or the
global application object (NSApp
in AppKit) can also receive and handle those messages.
3. Decorator
The Decorator design pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. As does subclassing, adaptation of the Decorator pattern allows you to incorporate new behavior without modifying existing code. Decorators wrap an object of the class whose behavior they extend. They implement the same interface as the object they wrap and add their own behavior either before or after delegating a task to the wrapped object. The Decorator pattern expresses the design principle that classes should be open to extension but closed to modification.
How Cocoa adapts Decorator Design Patterns?
Delegation
Delegation is a mechanism by which a host object embeds a weak
reference (weak in the sense that it’s a simple pointer
reference, unretained) to another object — its delegate — and
periodically sends messages to the delegate when it requires its
input for a task. The host object is generally an
“off-the-shelf” framework object (such as an
NSWindow
or
NSXMLParser
object) that is seeking to accomplish something, but can only do
so in a generic fashion. The delegate, which is almost always an
instance of a custom class, acts in coordination with the host
object, supplying program-specific behavior at certain points in
the task (see Figure 1). Thus delegation makes it possible to
modify or extend the behavior of another object without the need
for subclassing.
Cocoa uses the Decorator pattern in the implementation of
several of its classes, including
NSAttributedString
,
NSScrollView
, and
UIDatePicker
. The latter two classes are examples of compound views, which
group together simple objects of other view classes and
coordinate their interaction.
Uses and Limitations
Delegation is a common design in the Cocoa frameworks. Many
classes in the AppKit and UIKit frameworks send messages to
delegates, including
NSApplication
,
UIApplication
,
UITableView
, and several subclasses of
NSView
. Some classes in the Foundation framework, such as
NSXMLParser
and
NSStream
, also maintain delegates. You should always use a class’s
delegation mechanism instead of subclassing the class, unless
the delegation methods do not allow you to accomplish your goal.
Although you can dynamically change the delegate, only one object can be a delegate at a time. Thus if you want multiple objects to be informed of a particular program event at the same time, you cannot use delegation.
4. Facade
The Facade design pattern provides a unified interface to a set of interfaces in a subsystem. The pattern defines a higher-level interface that makes the subsystem easier to use by reducing complexity and hiding the communication and dependencies between subsystems.
How Cocoa adapts Facade Design Patterns?
NSImage
The
NSImage
class of the AppKit framework provides a unified interface for
loading and using images that can be bitmap-based (such as those
in JPEG, PNG, or TIFF format) or vector-based (such as those in
EPS or PDF format).
NSImage
can
keep more than one representation of the same image; each
representation is a kind of
NSImageRep
object.
NSImage
automates the choice of the representation that is appropriate
for a particular type of data and for a given display device. It
also hides the details of image manipulation and selection so
that the client can use many different underlying
representations interchangeably.
Uses and Limitations
Because
NSImage
supports several different representations of what an image is,
some requested attributes might not apply. For example, asking
an image for the color of a pixel does not work if the
underlying image representation is vector-based and
device-independent.