< Previous PageNext Page >

How Cocoa Adapts Design Patterns

You can find adaptations of design patterns throughout Cocoa. Mechanisms and architectures based on patterns are common in Cocoa frameworks and in the Objective-C runtime and language. Cocoa often puts its own distinctive spin on a pattern, its designs being influenced by factors such as language capabilities or existing architectures.

This section contains entries for most of the design patterns cataloged in Design Patterns: Elements of Reusable Object-Oriented Software. Each entry summarizes the pattern and describes the Cocoa implementations of it. Only patterns that Cocoa implements are listed, and each discussion of a pattern in the following sections takes place within a particular Cocoa context. It is recommended that you become familiar with these patterns, as you will find them useful in Cocoa software development.

Implementations of design patterns in Cocoa come in various forms. Some of the designs described in the following sections—such as protocols and categories—are features of the Objective-C language. In other cases, the “instance of a pattern” is implemented in one class or a group of related classes (for example, class clusters and singleton classes). And in other cases the pattern adaptation is a major framework architecture, such as the responder chain. Some of the pattern-based mechanisms you get almost “for free” while others require some work on your part. And even if Cocoa does not implement a pattern, you are encouraged to do so yourself when the situation warrants it; for example, object composition (Decorator pattern) is often a better technique than subclassing for extending class behavior.

Two design patterns are not discussed below, Model-View-Controller (MVC) and object modeling. MVC is a compound or aggregate pattern, meaning that it is based on several catalog patterns. Object modeling has no counterpart in the Gang of Four catalog, instead originating from the domain of relational databases. Yet MVC and object modeling are perhaps the most important and pervasive design patterns or metaphors in Cocoa, and to a large extent they are interrelated patterns. They play a crucial role in the design of several technologies, including bindings, undo management, scripting, and the document architecture. To learn more about these patterns, see “The Model-View-Controller Design Pattern” and “Object Modeling”.

In this section:

Abstract Factory
Adapter
Chain of Responsibility
Command
Composite
Decorator
Facade
Iterator
Mediator
Memento
Observer
Proxy
Singleton
Template Method


Abstract Factory

Provide an interface for creating families of related or dependent objects without specifying their concrete classes. The client is decoupled from any of the specifics of the concrete object obtained from the factory.

Class Cluster

A class cluster is an architecture that groups a number of private, concrete subclasses under a public, abstract superclass. The abstract superclass declares methods for creating instances of its private subclasses. The superclass dispenses an object of the proper concrete subclass based on the creation method invoked. Each object returned may belong to different private concrete subclass.

Cocoa limits class clusters to the generation of objects whose storage of data may vary depending on circumstances. The Foundation framework has class clusters for NSString, NSData, NSDictionary, NSSet, and NSArray objects. The public superclasses include the aforementioned immutable classes as well as the complementary mutable classes NSMutableString, NSMutableData, NSMutableDictionary, NSMutableSet, and NSMutableArray.

Uses and Limitations

You use one of the public classes of a class cluster when you want to create immutable or mutable objects of the type represented by the cluster. With class clusters there is a trade-off between simplicity and extensibility. A class cluster simplifies the interface to a class and thus makes it easier to learn and use the class. However, it is generally more difficult to create custom subclasses of the abstract class of a class cluster.

Further Reading: “Class Clusters” provides more information about class clusters in Cocoa.

Adapter

Convert the interface of a class into another interface 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.

Protocols

A protocol is a language-level (Objective-C) feature that makes it possible to define interfaces that are instances of the Adapter pattern. (In Java, “interface” is synonymous with “protocol.”) If you want a client object to communicate with another object, but their incompatible interfaces make that difficult, you can define a protocol, which is essentially a series of method declarations unassociated with a class. The class of the other object then formally adopts the protocol and “conforms” to it by implementing all of the methods of the protocol. The client object can then send messages to the other object through the protocol interface.

Protocols make a set of method declarations independent of the class hierarchy. They make it possible to group objects on the basis of conformance to a protocol as well as class inheritance. The NSObject method conformsToProtocol: permits you to verify an object’s protocol affiliation.

In addition to formal protocols, Cocoa has the notion of informal protocols. This type of protocol is a category on the NSObject class, thus making any object a potential implementer of any method in the category (see “Categories”). The methods in an informal protocol can be selectively implemented. Informal protocols are part of the implementation of the delegation mechanism (see “Delegation”).

Note that the design of protocols does not perfectly match the Adapter pattern. But it is a means for allowing classes with otherwise incompatible interfaces to work together.

Uses and Limitations

You primarily use a protocol to declare an interface that hierarchically unrelated classes are expected to conform to if they wish to communicate. But you can also use protocols to declare an interface of an object while concealing its class. The Cocoa frameworks include many formal protocols that enable custom subclasses to communicate with them for specific purposes. For example, the Foundation framework includes the NSObject, NSCopying, and NSCoding protocols, which are all very important ones. Application Kit protocols include NSDraggingInfo, NSTextInput, and NSChangeSpelling.

Formal protocols require the conforming class to implement all declared methods. They are also fragile; once you define a protocol and make it available to other classes, future changes to it can break those classes.

Further Reading: More more information on formal protocols, see the discussion in “Extending Classes” in The Objective-C Programming Language.

Chain of Responsibility

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. Each object either handles the request or passes it to the next object in the chain.

Responder Chain

The Application Kit framework includes an architecture known as the responder chain. This chain consists of a series of responder objects (that is, objects inheriting from NSResponder) 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 or the delegate of the window object or the global application object. The exact 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.

A similar chain of responders exists for error handling in an application.

The design of the view hierarchy, which is closely related to the responder chain, adapts the Composite pattern (“Composite”). Action messages—messages originating from control objects—are based on the target-action mechanism, which is an instance of the Command pattern (“Command”).

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 methods, you can receive and handle events and action messages. A custom object that is a delegate of a window object or NSApp, the global application object, can also receive and handle those messages.

You can also programmatically inject custom responders into the responder chain and you can programmatically manipulate the order of responders.

Further Reading: The responder chain for events and action messages and the responder chain for handling errors are described in Cocoa Event-Handling Guide and Error Handling Programming Guide For Cocoa. This document summarizes the view hierarchy in the section on the “Composite” pattern and is more fully described in “The Core Application Architecture”.

Command

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. The request object binds together one or more actions on a specific receiver. The Command pattern separates an object making a request from the objects that receive and execute that request.

Invocation Objects

An instance of the NSInvocation class encapsulates an Objective-C message. An invocation object contains a target object, method selector, and method arguments. You can dynamically change the target of the message dispatched by the invocation object as well as its arguments; once the invocation is executed, you can also obtain the return value from the object. With a single invocation object, you can repeatedly invoke a message with multiple variations in target and arguments.

The creation of an NSInvocation object requires an NSMethodSignature object, which is an object that encapsulates type information related to the arguments and return value of a method. An NSMethodSignature object, in turn, is created from a method selector. The implementation of NSInvocation also makes use of functions of the Objective-C runtime.

Uses and Limitations

NSInvocation objects are part of the programmatic interfaces of distributed objects, undo management, message forwarding, and timers. You can also use invocation objects in similar contexts where you need to decouple an object sending a message from the object that receives the message.

Distributed objects is a technology for interprocess communication. See “Proxy” for more on distributed objects.

Further Reading: See the NSInvocation class reference documentation for details of invocation objects. Also, consult the following documents for information about related technologies: Distributed Objects Programming Topics, Undo Architecture, Timers, and the section on forwarding in The Objective-C Programming Language.

Target-Action

The target-action mechanism enables a control object—that is, an object such as a button, slider, or text field—to send a message to another object that can interpret the message and handle it as an application-specific instruction. The receiving object, or the target, is usually a custom controller object. The message—named an action message—is determined by a selector, a unique runtime identifier of a method. The cell object that a control owns typically encapsulates the target and action; the control sends the message when the user clicks or otherwise activates it. (A menu item also encapsulates target and action, and sends an action message when the user chooses it.) The target-action mechanism can work on the basis of a selector (and not a method signature) because the signature of an action method by convention is always the same.

Uses and Limitations

You can set a control’s action and target when you construct a program’s user interface using the Interface Builder application. You thereby let the control initiate custom behavior without writing any code for the control itself. The action selector and target connection are archived in a nib file and are restored when the nib is unarchived. You can also change the target and action dynamically by sending the control or its cell setTarget: and setAction: messages.

Target-action has frequently been used to instruct a custom controller object to transfer data from the user interface to a model object, or to display data in a model object. The Cocoa bindings technology obviates the need to use target-action for this purpose. See Cocoa Bindings Programming Topics for more about this technology.

Controls and cells in the Application Kit do not retain their targets. Instead they maintain a weak reference to them. See “Ownership of Delegates, Observers, and Targets” for further information.

Further Reading: See “The Target-Action Mechanism” for further information.

Composite

Compose related objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

The Composite pattern is part of the Model-View-Controller aggregate pattern.

View Hierarchy

The views (NSView objects) in a window are internally structured into a view hierarchy. At the root of the hierarchy is a window (NSWindow object) and its content view, a transparent view that fills the window’s content rectangle. Views that are added to the content view become subviews of it, and they become the superviews of any views added to them. A view can have one (and only one) superview and zero or more subviews. Visually you apprehend this structure as containment: a superview contains its subviews. Figure 4-2 shows the structural and visual aspects of the view hierarchy.


Figure 4-2  The view hierarchy, structural and visual

The view hierarchy, structural and visual

The view hierarchy is a structural architecture that plays a part in both drawing and event handling. A view has two bounding rectangles, its frame and its bounds, that affect how graphics operations with the view take place. The frame is the exterior boundary; it locates the view in its superview’s coordinate system, defines its size, and clips drawing to its edges. The bounds, the interior bounding rectangle, defines the internal coordinate system of the surface where the view draws itself.

When a window is asked by the windowing system to prepare itself for display, superviews are asked to render themselves before their subviews. When you send some messages to a view—for example, a message that requests it to redraw itself—the message is propagated to subviews. You can thus treat a branch of the view hierarchy as a unified view.

The view hierarchy is also used by the responder chain for handling events and action messages. See the summary of the responder chain in the Chain of Responsibility pattern entry (“Chain of Responsibility”).

Uses and Limitations

You create or modify a view hierarchy whenever you add a view to another view, either programmatically or using Interface Builder. The Application Kit framework automatically handles all the relationships associated with the view hierarchy.

Further Reading: For learn more about the view hierarchy, read “The View Hierarchy” in this document. Cocoa Drawing Guide also discusses the view hierarchy.

Decorator

Attach 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.

General Comments

Decorator is a pattern for object composition, which is something that you are encouraged to do in your own code (see “When to Make a Subclass”). Cocoa, however, provides some classes and mechanisms of its own (discussed in the sections below) that are based on the pattern. In these implementations, the extending object does not completely duplicate the interface of the object that it wraps, although the implementations use different techniques for interface sharing.

Cocoa uses the Decorator pattern in the implementation of several of its classes, including NSAttributedString, NSScrollView, and NSTableView. The latter two class are examples of compound views, which group together simple objects of other view classes and coordinate their interaction.

Delegation

Delegation is a mechanism in which a host object embeds a weak reference (an unretained outlet) 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 a 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 4-3). Thus delegation makes it possible to modify or extend the behavior of another object without the need for subclassing.


Figure 4-3  Framework object sending a message to its delegate

Framework object sending a message to its delegate

Delegation, in the simple sense of one object delegating a task to another object, is a common technique in object-oriented programming. However, Cocoa implements delegation in a unique way. A host class uses informal protocols—categories on NSObject—to define interfaces that the delegate object may choose to implement. The delegate does not have to implement all of the methods in the protocol, as it would with formal protocols. Before it attempts to send a message to its delegate, the host object determines if it implements the method (via a respondsToSelector: message) to avoid runtime exceptions. For more on formal and informal protocols, see “Protocols”.

Some classes in the Cocoa frameworks also send messages to their data sources. A data source is identical in all respects to a delegate, except that the intent is to provide the host object with data to populate a browser, a table view, or similar user-interface view. A data source also may be required to implement some methods of the protocol, unlike a delegate.

Delegation is not a strict implementation of the Decorator pattern. The host (delegating) object does not wrap an instance of the class it wants to extend; indeed, it’s the other way around, in that the delegate is specializing the behavior of the delegating framework class. There is no sharing of interface either, other than the delegation methods declared by the framework class.

Delegation in Cocoa is also part of the Template Method pattern (“Template Method”).

Uses and Limitations

Delegation is a common design in the Cocoa frameworks. Many classes in the Application Kit framework send messages to delegates, including NSApplication, NSWindow, 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. However, you can use the notification mechanism for this purpose. A delegate automatically receives notifications from its delegating framework object as long as the delegate implements one or more of the notification methods declared by the framework class. See the discussion of notifications in the Observer pattern (“Observer”).

Delegating objects in the Application Kit do not retain their delegates or data sources. Instead they maintain a weak reference to them. See “Ownership of Delegates, Observers, and Targets” for further information.

Further Reading: For further information on delegation, see “Delegates and Data Sources”“.

Categories

A category is a feature of the Objective-C language that enables you to add methods (interface and implementation) to a class without having to make a subclass. There is no runtime difference—within the scope of your program—between the original methods of the class and the methods added by the category. The methods in the category become part of the class type and are inherited by all the class’s subclasses.

As with delegation, categories are not a strict adaptation of the Decorator pattern, fulfilling the intent but taking a different path to implementing that intent. The behavior added by categories is a compile-time artifact, and is not something dynamically acquired. Moreover, categories do not encapsulate an instance of the class being extended.

Uses and Limitations

The Cocoa frameworks define numerous categories, most of them informal protocols (which are summarized in “Protocols”). Often they use categories to group related methods. You may implement categories in your code to extend classes without subclassing or to group related methods. However, you should be aware of these caveats:

Further Reading: See “Extending Classes” in The Objective-C Programming Language for more information on categories.

Facade

Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use by reducing complexity and hiding the communication and dependencies between subsystems.

NSImage

The NSImage class provides a unified interface for loading and using images that can be bitmap-based (such as JPEG, PNG, or TIFF format) or vector-based (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 a image for the color of a pixel will not work if the underlying image representation is vector-based and device-independent.

Note: See Cocoa Drawing Guide for a discussion of NSImage and image representations.

Iterator

Provide a way to access the elements of an aggregate object (that is, a collection) sequentially without exposing its underlying representation. The Iterator pattern transfers the responsibility for accessing and traversing the elements of a collection from the collection itself to an iterator object. The iterator defines an interface for accessing collection elements and keeps track of the current element. Different iterators can carry out different traversal policies.

NSEnumerator

The NSEnumerator class in the Foundation framework implements the Iterator pattern. The private, concrete subclass of the abstract NSEnumerator class returns enumerator objects that sequentially traverse collections of various types—arrays, sets, dictionaries (values and keys)—returning objects in the collection to clients.

NSDirectoryEnumerator is a distantly related class. Instances of this class recursively enumerate the contents of a directory in the file system.

Uses and Limitations

The collection classes such as NSArray, NSSet, and NSDictionary include methods that return an enumerator appropriate to the type of collection. All enumerators work in the same manner. You send a nextObject message to the enumerator object in a loop that exits when nil is returned instead of the next object in the collection.

Mediator

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. These objects can thus remain more reusable.

A Mediator object centralizes complex communication and control logic between objects in a system. These objects tell a Mediator object when their state changes and, in turn, respond to requests from Mediator.

Controller Classes

The Model-View-Controller design pattern assigns roles to the objects in an object-oriented system such as an application. They can be model objects, which contain the data of the application and manipulate that data; they can be view objects, which present the data and respond to user actions; or they can be controller objects, which mediate between the model and view objects. Controller objects fit the Mediator pattern.

In Cocoa, controller objects can be of two general types: mediating controllers or coordinating controllers. Mediating controllers mediate the flow of data between view objects and model objects in an application. Mediating controllers are typically NSController objects. Coordinating controllers implement the centralized communication and control logic for an application, acting as delegates for framework objects and as targets for action messages. They are typically NSWindowController objects or instances of custom NSObject subclasses. Because they are so highly specialized for a particular program, coordinating controllers tend not to be reusable.

The abstract class NSController and its concrete subclasses in the Application Kit framework are part of the Cocoa technology of bindings, which automatically synchronizes the data contained in model objects and displayed and edited in view objects. For example, if a user edits a string in a text field, bindings communicates that change—through a mediating controller—to the appropriate property of the bound model object. All programmers need to do is properly design their model objects and, using Interface Builder, establish bindings between the view, controller, and model objects of a program.

Instances of the concrete public controller classes are available on Interface Builder palette and hence are highly reusable. They provide services such as the management of selections and placeholder values. These objects perform the following specific functions:

Uses and Limitations

Generally you use NSController objects as mediating controllers because these objects are designed to communicate data between the view objects and model objects of an application. To use a mediating controller, you typically drag the object from an Interface Builder palette, specify the model-object property keys, and establish the bindings between view and model objects using the Bindings pane of the Interface Builder Info window. You can also subclass NSController or one of its subclasses to get more specialized behavior.

You can potentially make bindings between almost any pair of objects as long as those objects comply with the NSKeyValueCoding and NSKeyValueObserving informal protocols. But it's recommended that you make bindings through mediating controllers to get all the benefits NSController and its subclasses give you.

Coordinating controllers centralize communication and control logic in an application by

You usually make all of the above connections—outlets, target-action, and delegate—in Interface Builder, which archives them in the application’s nib file.

Further Reading: See “The Model-View-Controller Design Pattern” for a discussion of mediating controllers, coordinating controllers, and design decisions related to controllers. Cocoa Bindings Programming Topics describes the mediating controller classes in detail.

Memento

Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later. The Memento pattern keeps the important state of a key object external from that object to maintain cohesion.

Archiving

Archiving converts the objects in a program, along with those objects’ properties (attributes and relationships) into an archive that can be stored in the file system or transmitted between processes or across a network. The archive captures the object graph of a program as an architecture-independent stream of bytes that preserves the identity of the objects and the relationships among them. Because an object’s type is stored along with its data, an object decoded from a stream of bytes is normally instantiated using the same class of the object that was originally encoded.

Uses and Limitations

Generally, you want to archive those objects in your program whose state you want to preserve. Model objects almost always fall into this category. You write an object to an archive by encoding it, and you read that object from an archive by decoding it. Encoding and decoding are operations that you perform using an NSCoder object, preferably using the keyed archiving technique (requiring you to invoke methods of the NSKeyedArchiver and NSKeyedUnarchiver classes). The object being encoded and decoded must conform to the NSCoding protocol; the methods of this protocol are invoked during archiving.

Further Reading: See Archives and Serializations Programming Guide for Cocoa for further information about archiving.

Property List Serialization

A property list is a simple, structured serialization of an object graph that uses only objects of the following classes: NSDictionary, NSArray, NSString, NSData, NSDate, and NSNumber. These objects are commonly referred to as property list objects. Several Cocoa framework classes offer methods to serialize these property list objects and define special formats for the data stream recording the contents of the objects and their hierarchical relationship. The NSPropertyListSerialization class provides class methods that serialize property list objects to and from an XML format or an optimized binary format.

Uses and Limitations

If the objects in an object graph are simple, property list serialization is a flexible, portable, and adequate means to capture and externalize an object and its state. However, this form of serialization has its limitations. It does not preserve the full class identity of objects, only the general kind (array, dictionary, string, and so on). Thus an object restored from a property list might be of a different class than its original class. This is especially an issue when the mutability of an object can vary. Property list serialization also doesn’t keep track of objects that are referenced multiple times in an object, potentially resulting in multiple instances upon deserialization that was a single instance in the original object graph.

Further Reading: See Archives and Serializations Programming Guide for Cocoa for further information on property list serialization.

Core Data

Core Data is a framework and an architecture for managing object graphs and making them persistent. It is this second capability—object persistence—that makes Core Data an adaptation of the Memento pattern.

In the Core Data architecture, a central object called the managed object context manages the various model objects in an application's object graph. Below the managed object context is the persistence stack for that object graph—a collection of framework objects that mediate between the model objects and external data stores, such as XML files or relational databases. The persistence-stack objects map between data in the store and corresponding objects in the managed data context and, when there are multiple data stores, present them to the managed object context as a single aggregate store.

The design of Core Data is also heavily influenced by the Model-View-Controller and object modeling patterns.

Important: The Core Data framework was introduced in Mac OS X v10.4.

Uses and Limitations

Core Data is particularly useful in the development of enterprise applications where complex graphs of model objects must be defined, managed, and transparently archived and unarchived to and from data stores. The Xcode development environment includes project templates and design tools that reduce the programming effort required to create the two general types of Core Data applications, those that are document-based and those that are not document-based. The Interface Builder application also includes configurable Core Data framework objects on its palettes.

Further Reading: In this document, “Other Cocoa Architectures” contains a summary of Core Data. To learn more about Core Data, read Core Data Programming Guide. The tutorials NSPersistentDocument Core Data Tutorial and Low-Level Core Data Tutorial step you through the basic procedure for creating document-based and non–document-based Core Data applications.

Observer

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. The Observer pattern is essentially a publish-and-subscribe model in which the subject and its observers are loosely coupled. Communication can take place between the observing and observed objects without either needing to know much about the other.

Notifications

The notification mechanism of Cocoa implements one-to-many broadcast of messages according to the Observer pattern. Objects in a program add themselves or other objects to a list of observers of one or more notifications, each of which is identified by a global string (the notification name). The object that wants to notify other objects—the observed object—creates a notification object and posts it to a notification center. The notification center determines the observers of a particular notification and sends the notification to them via a message. The methods invoked by the notification message must conform to a certain single-parameter signature. The parameter of the method is the notification object, which contains the notification name, the observed object, and a dictionary containing any supplemental information.

Posting a notification is a synchronous procedure. The posting object doesn't regain control until the notification center has broadcast the notification to all observers. For asynchronous behavior, you can put the notification in a notification queue; control returns immediately to the posting object and the notification center broadcasts the notification when it reaches the top of the queue.

Regular notifications—that is, those broadcast by the notification center—are intraprocess only. If you want to broadcast notifications to other processes, you can use the distributed notification center and its related API.

Uses and Limitations

You can use notifications for a variety of reasons. For example, you could broadcast a notification to change how user-interface elements display information based on a certain event elsewhere in the program. Or you could use notifications as a way to ensure that objects in a document save their state before the document window is closed. The general purpose of notifications is to inform other objects of program events so they can respond appropriately.

But objects receiving notifications can react only after the event has occurred. This is a significant difference from delegation. The delegate is given a chance to reject or modify the operation proposed by the delegating object. Observing objects, on the other hand, cannot directly affect an impending operation.

The notification classes are NSNotification (for notification objects), NSNotificationCenter (to post notifications and add observers), NSNotificationQueue (to enqueue notifications), and NSDistributedNotificationCenter. Many Cocoa framework classes publish and post notifications that any object can observe.

Further Reading: “Notifications” describes notification mechanism in greater detail and offers guidelines for its use.

Key-Value Observing

Key-value observing is a mechanism that allows objects to be notified of changes to specific properties of other objects. It is based on the NSKeyValueObserving informal protocol. Observed properties can be simple attributes, to-one relationships, or to-many relationships. In the context of the Model-View-Controller pattern, key-value observing is especially important because it enables view objects to observe—via the controller layer—changes in model objects. It is thus an essential component of the Cocoa bindings technology (see “Controller Classes”).

Cocoa provides a default “automatic” implementation of many NSKeyValueObserving methods that gives all complying objects a property-observing capability.

Uses and Limitations

Key-value observing is similar to the notification mechanism but is different in important respects. In key-value observing there is no central object that provides change notification for all observers. Instead, notifications of changes are directly transmitted to observing objects. Key-value observing is also directly tied to the values of specific object properties. The notification mechanism, on the other hand, is more broadly concerned with program events.

Objects that participate in key-value observing (KVO) must comply with certain requirements—or, in shorthand, be KVO-compliant. For automatic observing, this requires compliance with the requirements of key-value coding (KVC-compliance) and using the KVC-compliance methods (that is, accessor methods). Key-value coding is a related mechanism (based on a related informal protocol) for automatically getting and setting the values of object properties.

You can refine KVO notifications by disabling automatic observer notifications and implementing manual notifications using the methods of the NSKeyValueObserving informal protocol and associated categories.

Further Reading: See Key-Value Observing Programming Guide to learn more about the mechanism and underlying protocol. Also see the related documents Key-Value Coding Programming Guide and Cocoa Bindings Programming Topics.

Proxy

Provide a surrogate or placeholder for another object to control access to it. You use this pattern to create a representative object that controls access to another object, which may be remote, expensive to create, or in need of securing. This pattern is structurally similar to the Decorator pattern but it serves a different purpose; Decorator adds behavior to an object whereas Proxy controls access to an object.

NSProxy

The NSProxy class defines the interface for objects that act as placeholders or surrogates for other objects, even for objects that don’t yet exist. A proxy object typically forwards a message sent to it to the object that it represents, but it can also responds to the message by loading the represented object or transforming itself into it. Although NSProxy is an abstract class, it implements the NSObject protocol and other fundamental methods expected of a root object; it is, in fact, the root class of a hierarchy just as the NSObject class is.

Concrete subclasses of NSProxy can accomplish the stated goals of the Proxy pattern such as lazy instantiation of expensive objects or acting as sentry objects for security. NSDistantObject, a concrete subclass of NSProxy in the Foundation framework, implements a remote proxy for transparent distributed messaging. NSDistantObject objects are part of the architecture for distributed objects. By acting as proxies for objects in other processes or threads, they help to enable communication between objects in those threads or processes.

NSInvocation objects, which are an adaptation of the Command pattern, are also part of the distributed objects architecture (see “Invocation Objects”).

Uses and Limitations

Cocoa employs NSProxy objects only in distributed objects. The NSProxy objects are specifically instances of the concrete subclasses NSDistantObject and NSProtocolChecker. You can use distributed objects not only for interprocess messaging (on the same or different computers) but you can also use it to implement distributed computing or parallel processing. If you want to use proxy objects for other purposes, such as the creation of expensive resources or security, you have to implement your own concrete subclass of NSProxy.

Further Reading: To learn more about Cocoa proxy objects and the role they play in distributed messaging, read Distributed Objects Programming Topics.

Singleton

Ensure a class only has one instance, and provide a global point of access to it. The class keeps track of its sole instance and ensures that no other instance can be created. Singleton classes are appropriate for situations where it makes sense for a single object to provide access to a global resource.

Framework Classes

Several Cocoa framework classes are singletons. They include NSFileManager, NSWorkspace, and NSApplication. A process is limited to one instance of these classes. When a client asks the class for an instance, it gets a shared instance, which is lazily created upon the first request.

Uses and Limitations

Using the shared instance returned by a singleton class is no different from using an instance of a non-singleton class, except that you are prevented from copying, retaining, or releasing it (the related methods are re-implemented as null operations). You can create your own singleton classes if the situation warrants it.

Further Reading: “Cocoa Objects” explains how to create a singleton class.

Template Method

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. The Template Method pattern lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

Overridden Framework Methods

The Template Method pattern is a fundamental design of Cocoa, and indeed of object-oriented frameworks in general. The pattern in Cocoa lets custom components of a program hook themselves into an algorithm, but the framework components determine when and how they are needed. The programmatic interfaces of Cocoa classes often include methods that are meant to be overridden by subclasses. At runtime, the framework invokes these so-called generic methods at certain points in the task it is carrying out. The generic methods provide a structure for custom code to contribute program-specific behavior and data to the task being executed and coordinated by framework classes.

Uses and Limitations

To make use of the Cocoa adaptation of the Template Method pattern, you must create a subclass and override those methods that the framework invokes to insert application-specific input into the algorithm it is executing. If you are writing your own framework, you should probably include the pattern in the design.

Note: “Adding Behavior to a Cocoa Program” discusses the Cocoa adaptation of the Template Method pattern, especially in “Inheriting From a Cocoa Class”.

Document Architecture

The document architecture of Cocoa is a particular—and important—instance of the general design of overridden framework methods as an adaptation of the Template Method pattern. Cocoa applications that can create and manage multiple documents, each in its own window, are almost always based on the document architecture. In this architecture there are cooperating objects of three framework classes: NSDocument, NSWindowController, and NSDocumentController. NSDocument objects manage the model objects that represent the data of a document; upon user requests, they write that data to files and reload the data, recreating the model objects with it. NSWindowController objects manage the user interface of particular documents. The NSDocumentController object of a document-based application tracks and manages all open documents and otherwise coordinates the activities of the application. At runtime, each of these objects receives messages from the Application Kit requesting it to perform specific operations. The application developer must override many of the methods invoked by these messages to add application-specific behavior.

The design of the document architecture of Cocoa is also heavily influenced by the Model-View-Controller pattern.

Uses and Limitations

You can create a project for a document-based Cocoa application by choosing the Cocoa Document-based Application template from the New Project assistant in Xcode. Then you must implement a custom subclass of NSDocument and may choose to implement custom subclasses of NSWindowController and NSDocumentController. The Application Kit provides much of the document-management logic of the application for you.

Note: In this document “Other Cocoa Architectures” contains a summary of the document architecture. For the definitive documentation for this adaptation of the Template Method pattern, see Document-Based Applications Overview.



< Previous PageNext Page >


© 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-12-20)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.