Design Pattern 3
Design Pattern 3
Intent
Chain of Responsibility is a behavioral design pattern that lets you pass requests
along a chain of handlers. Upon receiving a request, each handler decides either to
process the request or to pass it to the next handler in the chain.
Problem
Imagine that you’re working on an online ordering system. You want to restrict access to
the system so only authenticated users can create orders. Also, users who have
administrative permissions must have full access to all orders.
After a bit of planning, you realized that these checks must be performed sequentially.
The application can attempt to authenticate a user to the system whenever it receives a
request that contains the user’s credentials. However, if those credentials aren’t correct
and authentication fails, there’s no reason to proceed with any other checks.
The request must pass a series of checks before the ordering system itself can
handle it.
During the next few months, you implemented several more of those sequential checks.
One of your colleagues suggested that it’s unsafe to pass raw data straight to the
ordering system. So you added an extra validation step to sanitize the data in a
request.
Later, somebody noticed that the system is vulnerable to brute force password
cracking. To negate this, you promptly added a check that filters repeated failed
requests coming from the same IP address.
Someone else suggested that you could speed up the system by returning
cached results on repeated requests containing the same data. Hence, you
added another check which lets the request pass through to the system only if
there’s no suitable cached response.
The bigger the code grew, the messier it became.
The code of the checks, which had already looked like a mess, became more and more
bloated as you added each new feature. Changing one check sometimes affected the
others. Worst of all, when you tried to reuse the checks to protect other components of
the system, you had to duplicate some of the code since those components required
some of the checks, but not all of them.
The system became very hard to comprehend and expensive to maintain. You
struggled with the code for a while, until one day you decided to refactor the whole
thing.
Solution
Like many other behavioral design patterns, the Chain of Responsibility relies on
transforming particular behaviors into stand-alone objects called handlers. In our case,
each check should be extracted to its own class with a single method that performs the
check. The request, along with its data, is passed to this method as an argument.
The pattern suggests that you link these handlers into a chain. Each linked handler has
a field for storing a reference to the next handler in the chain. In addition to processing a
request, handlers pass the request further along the chain. The request travels along
the chain until all handlers have had a chance to process it.
Here’s the best part: a handler can decide not to pass the request further down the
chain and effectively stop any further processing.
In our example with ordering systems, a handler performs the processing and then
decides whether to pass the request further down the chain. Assuming the request
contains the right data, all the handlers can execute their primary behavior, whether it’s
authentication checks or caching.
For instance, when a user clicks a button, the event propagates through the chain of
GUI elements that starts with the button, goes along its containers (like forms or
panels), and ends up with the main application window. The event is processed by the
first element in the chain that’s capable of handling it. This example is also noteworthy
because it shows that a chain can always be extracted from an object tree.
Real-World Analogy
The first thing you hear is the robotic voice of the autoresponder. It suggests nine
popular solutions to various problems, none of which are relevant to your case. After a
while, the robot connects you to a live operator.
Alas, the operator isn’t able to suggest anything specific either. He keeps quoting
lengthy excerpts from the manual, refusing to listen to your comments. After hearing the
phrase “have you tried turning the computer off and on again?” for the 10th time, you
demand to be connected to a proper engineer.
Eventually, the operator passes your call to one of the engineers, who had probably
longed for a live human chat for hours as he sat in his lonely server room in the dark
basement of some office building. The engineer tells you where to download proper
drivers for your new hardware and how to install them on Linux. Finally, the solution!
You end the call, bursting with joy.
Structure
1. The Handler declares the interface, common for all concrete handlers. It usually contains
just a single method for handling requests, but sometimes it may also have another method for
setting the next handler on the chain.
2. The Base Handler is an optional class where you can put the boilerplate code that’s
common to all handler classes.
Usually, this class defines a field for storing a reference to the next handler. The clients can build a
chain by passing a handler to the constructor or setter of the previous handler. The class may also
implement the default handling behavior: it can pass execution to the next handler after checking for
its existence.
3. Concrete Handlers contain the actual code for processing requests. Upon receiving a
request, each handler must decide whether to process it and, additionally, whether to pass it along
the chain.
Handlers are usually self-contained and immutable, accepting all necessary data just once via the
constructor.
4. The Client may compose chains just once or compose them dynamically, depending on the
application’s logic. Note that a request can be sent to any handler in the chain—it doesn’t have to be
the first one.
Pseudocode
In this example, the Chain of Responsibility pattern is responsible for displaying
contextual help information for active GUI elements.
The GUI classes are built with the Composite pattern. Each element is linked to its
container element. At any point, you can build a chain of elements that starts with the
element itself and goes through all of its container elements.
The application’s GUI is usually structured as an object tree. For example,
the Dialog class, which renders the main window of the app, would be the root of the
object tree. The dialog contains Panels, which might contain other panels or simple low-
level elements like Buttons and TextFields.
A simple component can show brief contextual tooltips, as long as the component has
some help text assigned. But more complex components define their own way of
showing contextual help, such as showing an excerpt from the manual or opening a
page in a browser.
method add(child) is
children.add(child)
child.container = this
method showHelp() is
if (modalHelpText != null)
// Show a modal window with the help text.
else
super.showHelp()
// ...same as above...
class Dialog extends Container is
field wikiPageURL: string
method showHelp() is
if (wikiPageURL != null)
// Open the wiki help page.
else
super.showHelp()
// Client code.
class Application is
// Every application configures the chain differently.
method createUI() is
dialog = new Dialog("Budget Reports")
dialog.wikiPageURL = "http://..."
panel = new Panel(0, 0, 400, 800)
panel.modalHelpText = "This panel does..."
ok = new Button(250, 760, 50, 20, "OK")
ok.tooltipText = "This is an OK button that..."
cancel = new Button(320, 760, 50, 20, "Cancel")
// ...
panel.add(ok)
panel.add(cancel)
dialog.add(panel)
Applicability
Use the Chain of Responsibility pattern when your program is expected to
process different kinds of requests in various ways, but the exact types of
requests and their sequences are unknown beforehand.
The pattern lets you link several handlers into one chain and, upon receiving a request,
“ask” each handler whether it can process it. This way all handlers get a chance to
process the request.
Use the pattern when it’s essential to execute several handlers in a particular
order.
Since you can link the handlers in the chain in any order, all requests will get through
the chain exactly as you planned.
Use the CoR pattern when the set of handlers and their order are supposed to
change at runtime.
If you provide setters for a reference field inside the handler classes, you’ll be able to
insert, remove or reorder handlers dynamically.
How to Implement
1. Declare the handler interface and describe the signature of a method for handling
requests.
Decide how the client will pass the request data into the method. The most flexible way
is to convert the request into an object and pass it to the handling method as an
argument.
This class should have a field for storing a reference to the next handler in the chain.
Consider making the class immutable. However, if you plan to modify chains at runtime,
you need to define a setter for altering the value of the reference field.
You can also implement the convenient default behavior for the handling method, which
is to forward the request to the next object unless there’s none left. Concrete handlers
will be able to use this behavior by calling the parent method.
3. One by one create concrete handler subclasses and implement their handling
methods. Each handler should make two decisions when receiving a request:
o Whether it’ll process the request.
o Whether it’ll pass the request along the chain.
4. The client may either assemble chains on its own or receive pre-built chains from
other objects. In the latter case, you must implement some factory classes to build
chains according to the configuration or environment settings.
5. The client may trigger any handler in the chain, not just the first one. The request
will be passed along the chain until some handler refuses to pass it further or until it
reaches the end of the chain.
6. Due to the dynamic nature of the chain, the client should be ready to handle the
following scenarios:
o The chain may consist of a single link.
o Some requests may not reach the end of the chain.
o Others may reach the end of the chain unhandled.
The pattern allows multiple objects to handle the request without coupling sender class to the
concrete classes of the receivers. The chain can be composed dynamically at runtime with any
handler that follows a standard handler interface.
Learn more about Chain of Responsibility
Popularity:
Usage examples: The Chain of Responsibility pattern isn’t a frequent guest in a Swift program
since it’s only relevant when code operates with chains of objects.
Conceptual Example
This example illustrates the structure of the Chain of Responsibility design pattern and focuses
on the following questions:
After learning about the pattern’s structure it’ll be easier for you to grasp the following example,
based on a real-world Swift use case.
Example.swift: Conceptual example
import XCTest
/// The Handler interface declares a method for building the chain of handlers.
/// It also declares a method for executing a request.
protocol Handler: class {
@discardableResult
func setNext(handler: Handler) -> Handler
extension Handler {
/// All Concrete Handlers either handle a request or pass it to the next handler
/// in the chain.
class MonkeyHandler: Handler {
if (request == "Nut") {
return "Squirrel: I'll eat the " + request + ".\n"
} else {
return nextHandler?.handle(request: request)
}
}
}
/// The client code is usually suited to work with a single handler. In most
/// cases, it is not even aware that the handler is part of a chain.
class Client {
// ...
static func someClientCode(handler: Handler) {
func test() {
/// The other part of the client code constructs the actual chain.
/// The client should be able to send a request to any handler, not just
/// the first one in the chain.
protocol Handler {
return next?.handle(request)
}
}
return next?.handle(request)
}
}
case emptyFirstName
case emptyLastName
case emptyEmail
case emptyPassword
case invalidEmail
case invalidPassword
case differentPasswords
case locationDisabled
case notificationsDisabled
protocol Request {
extension Request {
init(handler: Handler) {
self.handler = handler
super.init(nibName: nil, bundle: nil)
}
func loginButtonSelected() {
print("Login View Controller: User selected Login button")
func signUpButtonSelected() {
print("SignUp View Controller: User selected SignUp button")
func testChainOfResponsibilityRealWorld() {
loginController.loginButtonSelected()
signUpController.signUpButtonSelected()
}
}
Output.txt: Execution result
Client: Let's test Login flow!
Login View Controller: User selected Login button
Login View Controller: Preconditions are successfully validated
Intent
Command is a behavioral design pattern that turns a request into a stand-alone object
that contains all information about the request. This transformation lets you pass
requests as a method arguments, delay or queue a request’s execution, and support
undoable operations.
Problem
Imagine that you’re working on a new text-editor app. Your current task is to create a
toolbar with a bunch of buttons for various operations of the editor. You created a very
neat Button class that can be used for buttons on the toolbar, as well as for generic
buttons in various dialogs.
While all of these buttons look similar, they’re all supposed to do different things. Where
would you put the code for the various click handlers of these buttons? The simplest
solution is to create tons of subclasses for each place where the button is used. These
subclasses would contain the code that would have to be executed on a button click.
Before long, you realize that this approach is deeply flawed. First, you have an
enormous number of subclasses, and that would be okay if you weren’t risking breaking
the code in these subclasses each time you modify the base Button class. Put simply,
your GUI code has become awkwardly dependent on the volatile code of the business
logic.
Several classes implement the same functionality.
And here’s the ugliest part. Some operations, such as copying/pasting text, would need
to be invoked from multiple places. For example, a user could click a small “Copy”
button on the toolbar, or copy something via the context menu, or just hit Ctrl+C on the
keyboard.
Initially, when our app only had the toolbar, it was okay to place the implementation of
various operations into the button subclasses. In other words, having the code for
copying text inside the CopyButton subclass was fine. But then, when you implement
context menus, shortcuts, and other stuff, you have to either duplicate the operation’s
code in many classes or make menus dependent on buttons, which is an even worse
option.
Solution
Good software design is often based on the principle of separation of concerns, which
usually results in breaking an app into layers. The most common example: a layer for
the graphical user interface and another layer for the business logic. The GUI layer is
responsible for rendering a beautiful picture on the screen, capturing any input and
showing results of what the user and the app are doing. However, when it comes to
doing something important, like calculating the trajectory of the moon or composing an
annual report, the GUI layer delegates the work to the underlying layer of business
logic.
In the code it might look like this: a GUI object calls a method of a business logic object,
passing it some arguments. This process is usually described as one object sending
another a request.
Command objects serve as links between various GUI and business logic objects. From
now on, the GUI object doesn’t need to know what business logic object will receive the
request and how it’ll be processed. The GUI object just triggers the command, which
handles all the details.
You might have noticed one missing piece of the puzzle, which is the request
parameters. A GUI object might have supplied the business-layer object with some
parameters. Since the command execution method doesn’t have any parameters, how
would we pass the request details to the receiver? It turns out the command should be
either pre-configured with this data, or capable of getting it on its own.
The GUI objects delegate the work to commands.
Let’s get back to our text editor. After we apply the Command pattern, we no longer
need all those button subclasses to implement various click behaviors. It’s enough to
put a single field into the base Button class that stores a reference to a command object
and make the button execute that command on a click.
You’ll implement a bunch of command classes for every possible operation and link
them with particular buttons, depending on the buttons’ intended behavior.
Other GUI elements, such as menus, shortcuts or entire dialogs, can be implemented in
the same way. They’ll be linked to a command which gets executed when a user
interacts with the GUI element. As you’ve probably guessed by now, the elements
related to the same operations will be linked to the same commands, preventing any
code duplication.
Real-World Analogy
Structure
1. The Sender class (aka invoker) is responsible for initiating requests. This class must have a
field for storing a reference to a command object. The sender triggers that command instead of
sending the request directly to the receiver. Note that the sender isn’t responsible for creating the
command object. Usually, it gets a pre-created command from the client via the constructor.
2. The Command interface usually declares just a single method for executing the command.
3. Concrete Commands implement various kinds of requests. A concrete command isn’t
supposed to perform the work on its own, but rather to pass the call to one of the business logic
objects. However, for the sake of simplifying the code, these classes can be merged.
Parameters required to execute a method on a receiving object can be declared as fields in the
concrete command. You can make command objects immutable by only allowing the initialization of
these fields via the constructor.
4. The Receiver class contains some business logic. Almost any object may act as a receiver.
Most commands only handle the details of how a request is passed to the receiver, while the
receiver itself does the actual work.
5. The Client creates and configures concrete command objects. The client must pass all of
the request parameters, including a receiver instance, into the command’s constructor. After that, the
resulting command may be associated with one or multiple senders.
Pseudocode
In this example, the Command pattern helps to track the history of executed operations
and makes it possible to revert an operation if needed.
The client code (GUI elements, command history, etc.) isn’t coupled to concrete
command classes because it works with commands via the command interface. This
approach lets you introduce new commands into the app without breaking any existing
code.
// The base command class defines the common interface for all
// concrete commands.
abstract class Command is
protected field app: Application
protected field editor: Editor
protected field backup: text
// Last in...
method push(c: Command) is
// Push the command to the end of the history array.
// ...first out
method pop():Command is
// Get the most recent command from the history.
method getSelection() is
// Return selected text.
method deleteSelection() is
// Delete selected text.
method replaceSelection(text) is
// Insert the clipboard's contents at the current
// position.
// Take the most recent command from the history and run its
// undo method. Note that we don't know the class of that
// command. But we don't have to, since the command knows
// how to undo its own action.
method undo() is
command = history.pop()
if (command != null)
command.undo()
Applicability
Use the Command pattern when you want to parametrize objects with
operations.
The Command pattern can turn a specific method call into a stand-alone object. This
change opens up a lot of interesting uses: you can pass commands as method
arguments, store them inside other objects, switch linked commands at runtime, etc.
Here’s an example: you’re developing a GUI component such as a context menu, and
you want your users to be able to configure menu items that trigger operations when an
end user clicks an item.
Use the Command pattern when you want to queue operations, schedule their
execution, or execute them remotely.
As with any other object, a command can be serialized, which means converting it to a
string that can be easily written to a file or a database. Later, the string can be restored
as the initial command object. Thus, you can delay and schedule command execution.
But there’s even more! In the same way, you can queue, log or send commands over
the network.
Use the Command pattern when you want to implement reversible operations.
Although there are many ways to implement undo/redo, the Command pattern is
perhaps the most popular of all.
This method has two drawbacks. First, it isn’t that easy to save an application’s state
because some of it can be private. This problem can be mitigated with
the Memento pattern.
Second, the state backups may consume quite a lot of RAM. Therefore, sometimes you
can resort to an alternative implementation: instead of restoring the past state, the
command performs the inverse operation. The reverse operation also has a price: it
may turn out to be hard or even impossible to implement.
How to Implement
1. Declare the command interface with a single execution method.
2. Start extracting requests into concrete command classes that implement the
command interface. Each class must have a set of fields for storing the request
arguments along with a reference to the actual receiver object. All these values must be
initialized via the command’s constructor.
3. Identify classes that will act as senders. Add the fields for storing commands into
these classes. Senders should communicate with their commands only via the
command interface. Senders usually don’t create command objects on their own, but
rather get them from the client code.
4. Change the senders so they execute the command instead of sending a request
to the receiver directly.
5. The client should initialize objects in the following order:
o Create receivers.
o Create commands, and associate them with receivers if needed.
o Create senders, and associate them with specific commands.
Pros and Cons
Single Responsibility Principle. You can decouple classes that invoke operations
from classes that perform these operations.
Open/Closed Principle. You can introduce new commands into the app without
breaking existing client code.
You can implement undo/redo.
You can implement deferred execution of operations.
You can assemble a set of simple commands into a complex one.
The code may become more complicated since you’re introducing a whole new
layer between senders and receivers.
Command in Swift
Command is behavioral design pattern that converts requests or simple operations into
objects.
Popularity:
Usage examples: The Command pattern is pretty common in Swift code. Most often
it’s used as an alternative for callbacks to parameterizing UI elements with actions. It’s
also used for queueing tasks, tracking operations history, etc.
Conceptual Example
This example illustrates the structure of the Command design pattern and focuses on
the following questions:
Example.swift: Conceptual example
import XCTest
func execute()
}
func execute() {
print("SimpleCommand: See, I can do simple things like printing (" + payload
+ ")")
}
}
/// However, some commands can delegate more complex operations to other
/// objects, called "receivers."
class ComplexCommand: Command {
/// Complex commands can accept one or several receiver objects along with
/// any context data via the constructor.
init(_ receiver: Receiver, _ a: String, _ b: String) {
self.receiver = receiver
self.a = a
self.b = b
}
/// The Receiver classes contain some important business logic. They know how to
/// perform all kinds of operations, associated with carrying out a request. In
/// fact, any class may serve as a Receiver.
class Receiver {
/// The Invoker is associated with one or several commands. It sends a request
/// to the command.
class Invoker {
/// The Invoker does not depend on concrete command or receiver classes. The
/// Invoker passes a request to a receiver indirectly, by executing a
/// command.
func doSomethingImportant() {
onStart?.execute()
onFinish?.execute()
}
}
func test() {
/// The client code can parameterize an invoker with any commands.
Iterator
Intent
Iterator is a behavioral design pattern that lets you traverse elements of a collection
without exposing its underlying representation (list, stack, tree, etc.).
Problem
Collections are one of the most used data types in programming. Nonetheless, a
collection is just a container for a group of objects.
But no matter how a collection is structured, it must provide some way of accessing its
elements so that other code can use these elements. There should be a way to go
through each element of the collection without accessing the same elements over and
over.
This may sound like an easy job if you have a collection based on a list. You just loop
over all of the elements. But how do you sequentially traverse elements of a complex
data structure, such as a tree? For example, one day you might be just fine with depth-
first traversal of a tree. Yet the next day you might require breadth-first traversal. And
the next week, you might need something else, like random access to the tree
elements.
Adding more and more traversal algorithms to the collection gradually blurs its primary
responsibility, which is efficient data storage. Additionally, some algorithms might be
tailored for a specific application, so including them into a generic collection class would
be weird.
On the other hand, the client code that’s supposed to work with various collections may
not even care how they store their elements. However, since collections all provide
different ways of accessing their elements, you have no option other than to couple your
code to the specific collection classes.
Solution
The main idea of the Iterator pattern is to extract the traversal behavior of a collection
into a separate object called an iterator.
Iterators implement various traversal algorithms. Several iterator objects can traverse
the same collection at the same time.
In addition to implementing the algorithm itself, an iterator object encapsulates all of the
traversal details, such as the current position and how many elements are left till the
end. Because of this, several iterators can go through the same collection at the same
time, independently of each other.
Usually, iterators provide one primary method for fetching elements of the collection.
The client can keep running this method until it doesn’t return anything, which means
that the iterator has traversed all of the elements.
All iterators must implement the same interface. This makes the client code compatible
with any collection type or any traversal algorithm as long as there’s a proper iterator. If
you need a special way to traverse a collection, you just create a new iterator class,
without having to change the collection or the client.
Real-World Analogy
On the other hand, you could buy a virtual guide app for your smartphone and use it for
navigation. It’s smart and inexpensive, and you could be staying at some interesting
places for as long as you want.
A third alternative is that you could spend some of the trip’s budget and hire a local
guide who knows the city like the back of his hand. The guide would be able to tailor the
tour to your likings, show you every attraction and tell a lot of exciting stories. That’ll be
even more fun; but, alas, more expensive, too.
All of these options—the random directions born in your head, the smartphone
navigator or the human guide—act as iterators over the vast collection of sights and
attractions located in Rome.
Structure
4. Concrete Collections return new instances of a particular concrete iterator class each time
the client requests one. You might be wondering, where’s the rest of the collection’s code? Don’t
worry, it should be in the same class. It’s just that these details aren’t crucial to the actual pattern, so
we’re omitting them.
5. The Client works with both collections and iterators via their interfaces. This way the client
isn’t coupled to concrete classes, allowing you to use various collections and iterators with the same
client code.
Typically, clients don’t create iterators on their own, but instead get them from collections. Yet, in
certain cases, the client can create one directly; for example, when the client defines its own special
iterator.
Pseudocode
In this example, the Iterator pattern is used to walk through a special kind of collection
which encapsulates access to Facebook’s social graph. The collection provides several
iterators that can traverse profiles in various ways.
The client code isn’t coupled to concrete classes because it works with collections and
iterators only through interfaces. If you decide to connect your app to a new social
network, you simply need to provide new collection and iterator classes without
changing the existing code.
method hasMore() is
lazyInit()
return currentPosition < cache.length
method config() is
if working with Facebook
this.network = new Facebook()
if working with LinkedIn
this.network = new LinkedIn()
this.spammer = new SocialSpammer()
method sendSpamToFriends(profile) is
iterator = network.createFriendsIterator(profile.getId())
spammer.send(iterator, "Very important message")
method sendSpamToCoworkers(profile) is
iterator = network.createCoworkersIterator(profile.getId())
spammer.send(iterator, "Very important message")
Applicability
Use the Iterator pattern when your collection has a complex data structure under
the hood, but you want to hide its complexity from clients (either for convenience
or security reasons).
The iterator encapsulates the details of working with a complex data structure,
providing the client with several simple methods of accessing the collection elements.
While this approach is very convenient for the client, it also protects the collection from
careless or malicious actions which the client would be able to perform if working with
the collection directly.
Use the pattern to reduce duplication of the traversal code across your app.
The code of non-trivial iteration algorithms tends to be very bulky. When placed within
the business logic of an app, it may blur the responsibility of the original code and make
it less maintainable. Moving the traversal code to designated iterators can help you
make the code of the application more lean and clean.
Use the Iterator when you want your code to be able to traverse different data
structures or when types of these structures are unknown beforehand.
The pattern provides a couple of generic interfaces for both collections and iterators.
Given that your code now uses these interfaces, it’ll still work if you pass it various kinds
of collections and iterators that implement these interfaces.
How to Implement
1. Declare the iterator interface. At the very least, it must have a method for fetching
the next element from a collection. But for the sake of convenience you can add a
couple of other methods, such as fetching the previous element, tracking the current
position, and checking the end of the iteration.
2. Declare the collection interface and describe a method for fetching iterators. The
return type should be equal to that of the iterator interface. You may declare similar
methods if you plan to have several distinct groups of iterators.
3. Implement concrete iterator classes for the collections that you want to be
traversable with iterators. An iterator object must be linked with a single collection
instance. Usually, this link is established via the iterator’s constructor.
4. Implement the collection interface in your collection classes. The main idea is to
provide the client with a shortcut for creating iterators, tailored for a particular collection
class. The collection object must pass itself to the iterator’s constructor to establish a
link between them.
5. Go over the client code to replace all of the collection traversal code with the use
of iterators. The client fetches a new iterator object each time it needs to iterate over the
collection elements.
Applying the pattern can be an overkill if your app only works with simple collections.
Using an iterator may be less efficient than going through elements of some specialized
collections directly.
Iterator in Swift
Iterator is a behavioral design pattern that allows sequential traversal through a
complex data structure without exposing its internal details.
Thanks to the Iterator, clients can go over elements of different collections in a similar
fashion using a single iterator interface.
Learn more about Iterator
Usage of the pattern in Swift
Complexity:
Popularity:
Usage examples: The pattern is very common in Swift code. Many frameworks and
libraries use it to provide a standard way for traversing their collections.
Conceptual Example
This example illustrates the structure of the Iterator design pattern and focuses on the
following questions:
After learning about the pattern’s structure it’ll be easier for you to grasp the following
example, based on a real-world Swift use case.
Example.swift: Conceptual example
import XCTest
/// This is a collection that we're going to iterate through using an iterator
/// derived from IteratorProtocol.
class WordsCollection {
/// This is another collection that we'll provide AnyIterator for traversing its
/// items.
class NumbersCollection {
return AnyIterator {
defer { index -= 1 }
return index >= 0 ? self.items[index] : nil
}
}
}
/// Client does not know the internal representation of a given sequence.
class Client {
// ...
static func clientCode<S: Sequence>(sequence: S) {
for item in sequence {
print(item)
}
}
// ...
}
func testIteratorProtocol() {
let words = WordsCollection()
words.append("First")
words.append("Second")
words.append("Third")
func testAnyIterator() {
Mediator in Swift
Mediator is a behavioral design pattern that reduces coupling between components of
a program by making them communicate indirectly, through a special mediator object.
The Mediator makes it easy to modify, extend and reuse individual components
because they’re no longer dependent on the dozens of other classes.
Learn more about Mediator
Popularity:
Usage examples: The most popular usage of the Mediator pattern in Swift code is
facilitating communications between GUI components of an app. The synonym of the
Mediator is the Controller part of MVC pattern.
Conceptual Example
This example illustrates the structure of the Mediator design pattern and focuses on the
following questions:
After learning about the pattern’s structure it’ll be easier for you to grasp the following
example, based on a real-world Swift use case.
Example.swift: Conceptual example
import XCTest
/// The Mediator interface declares a method used by components to notify the
/// mediator about various events. The Mediator may react to these events and
/// pass the execution to other components.
protocol Mediator: AnyObject {
component1.update(mediator: self)
component2.update(mediator: self)
}
/// The Base Component provides the basic functionality of storing a mediator's
/// instance inside component objects.
class BaseComponent {
func doA() {
print("Component 1 does A.")
mediator?.notify(sender: self, event: "A")
}
func doB() {
print("Component 1 does B.\n")
mediator?.notify(sender: self, event: "B")
}
}
func doC() {
print("Component 2 does C.")
mediator?.notify(sender: self, event: "C")
}
func doD() {
print("Component 2 does D.")
mediator?.notify(sender: self, event: "D")
}
}
func testMediatorConceptual() {
print(mediator)
}
}
Output.txt: Execution result
Client triggers operation A.
Component 1 does A.
Mediator reacts on A and triggers following operations:
Component 2 does C.
Component 2 does C.
func test() {
feedVC.userLikedAllNews()
feedVC.userDislikedAllNews()
}
}
func userLikedAllNews() {
print("\n\nNews Feed: User LIKED all news models")
print("News Feed: I am telling to mediator about it...\n")
newsArray.forEach({ mediator?.likeAdded(to: $0) })
}
func userDislikedAllNews() {
print("\n\nNews Feed: User DISLIKED all news models")
print("News Feed: I am telling to mediator about it...\n")
newsArray.forEach({ mediator?.likeRemoved(from: $0) })
}
}
Intent
Mediator is a behavioral design pattern that lets you reduce chaotic dependencies
between objects. The pattern restricts direct communications between the objects and
forces them to collaborate only via a mediator object.
Problem
Say you have a dialog for creating and editing customer profiles. It consists of various
form controls such as text fields, checkboxes, buttons, etc.
Relations between elements of the user interface can become chaotic as the
application evolves.
Some of the form elements may interact with others. For instance, selecting the “I have
a dog” checkbox may reveal a hidden text field for entering the dog’s name. Another
example is the submit button that has to validate values of all fields before saving the
data.
Elements can have lots of relations with other elements. Hence, changes to some
elements may affect the others.
By having this logic implemented directly inside the code of the form elements you
make these elements’ classes much harder to reuse in other forms of the app. For
example, you won’t be able to use that checkbox class inside another form, because it’s
coupled to the dog’s text field. You can use either all the classes involved in rendering
the profile form, or none at all.
Solution
The Mediator pattern suggests that you should cease all direct communication between
the components which you want to make independent of each other. Instead, these
components must collaborate indirectly, by calling a special mediator object that
redirects the calls to appropriate components. As a result, the components depend only
on a single mediator class instead of being coupled to dozens of their colleagues.
In our example with the profile editing form, the dialog class itself may act as the
mediator. Most likely, the dialog class is already aware of all of its sub-elements, so you
won’t even need to introduce new dependencies into this class.
You can go further and make the dependency even looser by extracting the common
interface for all types of dialogs. The interface would declare the notification method
which all form elements can use to notify the dialog about events happening to those
elements. Thus, our submit button should now be able to work with any dialog that
implements that interface.
This way, the Mediator pattern lets you encapsulate a complex web of relations
between various objects inside a single mediator object. The fewer dependencies a
class has, the easier it becomes to modify, extend or reuse that class.
Real-World Analogy
Aircraft pilots don’t talk to each other directly when deciding who gets to land their plane
next. All communication goes through the control tower.
Pilots of aircraft that approach or depart the airport control area don’t communicate
directly with each other. Instead, they speak to an air traffic controller, who sits in a tall
tower somewhere near the airstrip. Without the air traffic controller, pilots would need to
be aware of every plane in the vicinity of the airport, discussing landing priorities with a
committee of dozens of other pilots. That would probably skyrocket the airplane crash
statistics.
The tower doesn’t need to control the whole flight. It exists only to enforce constraints in
the terminal area because the number of involved actors there might be overwhelming
to a pilot.
Structure
1. Components are various classes that contain some business logic. Each component has a
reference to a mediator, declared with the type of the mediator interface. The component isn’t aware
of the actual class of the mediator, so you can reuse the component in other programs by linking it to
a different mediator.
4. Components must not be aware of other components. If something important happens within
or to a component, it must only notify the mediator. When the mediator receives the notification, it
can easily identify the sender, which might be just enough to decide what component should be
triggered in return.
From a component’s perspective, it all looks like a total black box. The sender doesn’t know who’ll
end up handling its request, and the receiver doesn’t know who sent the request in the first place.
Pseudocode
In this example, the Mediator pattern helps you eliminate mutual dependencies
between various UI classes: buttons, checkboxes and text labels.
In this example, the whole authentication dialog acts as the mediator. It knows how
concrete elements are supposed to collaborate and facilitates their indirect
communication. Upon receiving a notification about an event, the dialog decides what
element should address the event and redirects the call accordingly.
constructor AuthenticationDialog() is
// Create all component objects and pass the current
// mediator into their constructors to establish links.
constructor Component(dialog) is
this.dialog = dialog
method click() is
dialog.notify(this, "click")
method keypress() is
dialog.notify(this, "keypress")
Applicability
Use the Mediator pattern when it’s hard to change some of the classes because
they are tightly coupled to a bunch of other classes.
The pattern lets you extract all the relationships between classes into a separate class,
isolating any changes to a specific component from the rest of the components.
Use the pattern when you can’t reuse a component in a different program
because it’s too dependent on other components.
After you apply the Mediator, individual components become unaware of the other
components. They could still communicate with each other, albeit indirectly, through a
mediator object. To reuse a component in a different app, you need to provide it with a
new mediator class.
Use the Mediator when you find yourself creating tons of component subclasses
just to reuse some basic behavior in various contexts.
Since all relations between components are contained within the mediator, it’s easy to
define entirely new ways for these components to collaborate by introducing new
mediator classes, without having to change the components themselves.
How to Implement
1. Identify a group of tightly coupled classes which would benefit from being more
independent (e.g., for easier maintenance or simpler reuse of these classes).
2. Declare the mediator interface and describe the desired communication protocol
between mediators and various components. In most cases, a single method for
receiving notifications from components is sufficient.
This interface is crucial when you want to reuse component classes in different
contexts. As long as the component works with its mediator via the generic interface,
you can link the component with a different implementation of the mediator.
3. Implement the concrete mediator class. This class would benefit from storing
references to all of the components it manages.
4. You can go even further and make the mediator responsible for the creation and
destruction of component objects. After this, the mediator may resemble a factory or
a facade.
6. Change the components’ code so that they call the mediator’s notification
method instead of methods on other components. Extract the code that involves calling
other components into the mediator class. Execute this code whenever the mediator
receives notifications from that component.
When you’re confused, remember that you can implement the Mediator pattern in other
ways. For example, you can permanently link all the components to the same mediator
object. This implementation won’t resemble Observer but will still be an instance of the
Mediator pattern.
Now imagine a program where all components have become publishers, allowing
dynamic connections between each other. There won’t be a centralized mediator object,
only a distributed set of observers.
Mediator in Swift
Mediator is a behavioral design pattern that reduces coupling between components of
a program by making them communicate indirectly, through a special mediator object.
The Mediator makes it easy to modify, extend and reuse individual components
because they’re no longer dependent on the dozens of other classes.
Learn more about Mediator
Usage of the pattern in Swift
Complexity:
Popularity:
Usage examples: The most popular usage of the Mediator pattern in Swift code is
facilitating communications between GUI components of an app. The synonym of the
Mediator is the Controller part of MVC pattern.
Conceptual Example
This example illustrates the structure of the Mediator design pattern and focuses on the
following questions:
After learning about the pattern’s structure it’ll be easier for you to grasp the following
example, based on a real-world Swift use case.
Example.swift: Conceptual example
import XCTest
/// The Mediator interface declares a method used by components to notify the
/// mediator about various events. The Mediator may react to these events and
/// pass the execution to other components.
protocol Mediator: AnyObject {
component1.update(mediator: self)
component2.update(mediator: self)
}
func notify(sender: BaseComponent, event: String) {
if event == "A" {
print("Mediator reacts on A and triggers following operations:")
self.component2.doC()
}
else if (event == "D") {
print("Mediator reacts on D and triggers following operations:")
self.component1.doB()
self.component2.doC()
}
}
}
/// The Base Component provides the basic functionality of storing a mediator's
/// instance inside component objects.
class BaseComponent {
func doA() {
print("Component 1 does A.")
mediator?.notify(sender: self, event: "A")
}
func doB() {
print("Component 1 does B.\n")
mediator?.notify(sender: self, event: "B")
}
}
func doC() {
print("Component 2 does C.")
mediator?.notify(sender: self, event: "C")
}
func doD() {
print("Component 2 does D.")
mediator?.notify(sender: self, event: "D")
}
}
func testMediatorConceptual() {
print(mediator)
}
}
Output.txt: Execution result
Client triggers operation A.
Component 1 does A.
Mediator reacts on A and triggers following operations:
Component 2 does C.
Component 2 does C.
func test() {
feedVC.userLikedAllNews()
feedVC.userDislikedAllNews()
}
}
func userLikedAllNews() {
print("\n\nNews Feed: User LIKED all news models")
print("News Feed: I am telling to mediator about it...\n")
newsArray.forEach({ mediator?.likeAdded(to: $0) })
}
func userDislikedAllNews() {
print("\n\nNews Feed: User DISLIKED all news models")
print("News Feed: I am telling to mediator about it...\n")
newsArray.forEach({ mediator?.likeRemoved(from: $0) })
}
}
class NewsDetailViewController: ScreenUpdatable {
Memento
Also known as: Snapshot
Intent
Memento is a behavioral design pattern that lets you save and restore the previous
state of an object without revealing the details of its implementation.
Problem
Imagine that you’re creating a text editor app. In addition to simple text editing, your
editor can format text, insert inline images, etc.
At some point, you decided to let users undo any operations carried out on the text. This
feature has become so common over the years that nowadays people expect every app
to have it. For the implementation, you chose to take the direct approach. Before
performing any operation, the app records the state of all objects and saves it in some
storage. Later, when a user decides to revert an action, the app fetches the latest
snapshot from the history and uses it to restore the state of all objects.
Before executing an operation, the app saves a snapshot of the objects’ state, which
can later be used to restore objects to their previous state.
Let’s think about those state snapshots. How exactly would you produce one? You’d
probably need to go over all the fields in an object and copy their values into storage.
However, this would only work if the object had quite relaxed access restrictions to its
contents. Unfortunately, most real objects won’t let others peek inside them that easily,
hiding all significant data in private fields.
Ignore that problem for now and let’s assume that our objects behave like hippies:
preferring open relations and keeping their state public. While this approach would solve
the immediate problem and let you produce snapshots of objects’ states at will, it still
has some serious issues. In the future, you might decide to refactor some of the editor
classes, or add or remove some of the fields. Sounds easy, but this would also require
changing the classes responsible for copying the state of the affected objects.
How to make a copy of the object’s private state?
But there’s more. Let’s consider the actual “snapshots” of the editor’s state. What data
does it contain? At a bare minimum, it must contain the actual text, cursor coordinates,
current scroll position, etc. To make a snapshot, you’d need to collect these values and
put them into some kind of container.
Most likely, you’re going to store lots of these container objects inside some list that
would represent the history. Therefore the containers would probably end up being
objects of one class. The class would have almost no methods, but lots of fields that
mirror the editor’s state. To allow other objects to write and read data to and from a
snapshot, you’d probably need to make its fields public. That would expose all the
editor’s states, private or not. Other classes would become dependent on every little
change to the snapshot class, which would otherwise happen within private fields and
methods without affecting outer classes.
It looks like we’ve reached a dead end: you either expose all internal details of classes,
making them too fragile, or restrict access to their state, making it impossible to produce
snapshots. Is there any other way to implement the "undo"?
Solution
All problems that we’ve just experienced are caused by broken encapsulation. Some
objects try to do more than they are supposed to. To collect the data required to perform
some action, they invade the private space of other objects instead of letting these
objects perform the actual action.
The Memento pattern delegates creating the state snapshots to the actual owner of that
state, the originator object. Hence, instead of other objects trying to copy the editor’s
state from the “outside,” the editor class itself can make the snapshot since it has full
access to its own state.
The pattern suggests storing the copy of the object’s state in a special object
called memento. The contents of the memento aren’t accessible to any other object
except the one that produced it. Other objects must communicate with mementos using
a limited interface which may allow fetching the snapshot’s metadata (creation time, the
name of the performed operation, etc.), but not the original object’s state contained in
the snapshot.
The originator has full access to the memento, whereas the caretaker can only access
the metadata.
Such a restrictive policy lets you store mementos inside other objects, usually
called caretakers. Since the caretaker works with the memento only via the limited
interface, it’s not able to tamper with the state stored inside the memento. At the same
time, the originator has access to all fields inside the memento, allowing it to restore its
previous state at will.
In our text editor example, we can create a separate history class to act as the
caretaker. A stack of mementos stored inside the caretaker will grow each time the
editor is about to execute an operation. You could even render this stack within the
app’s UI, displaying the history of previously performed operations to a user.
When a user triggers the undo, the history grabs the most recent memento from the
stack and passes it back to the editor, requesting a roll-back. Since the editor has full
access to the memento, it changes its own state with the values taken from the
memento.
Structure
Implementation based on nested classes
The classic implementation of the pattern relies on support for nested classes, available
in many popular programming languages (such as C++, C#, and Java).
1. The Originator class can produce snapshots of its own state, as well as restore its state
from snapshots when needed.
2. The Memento is a value object that acts as a snapshot of the originator’s state. It’s a
common practice to make the memento immutable and pass it the data only once, via the
constructor.
3. The Caretaker knows not only “when” and “why” to capture the originator’s state, but also
when the state should be restored.
A caretaker can keep track of the originator’s history by storing a stack of mementos. When the
originator has to travel back in history, the caretaker fetches the topmost memento from the stack
and passes it to the originator’s restoration method.
4. In this implementation, the memento class is nested inside the originator. This lets the
originator access the fields and methods of the memento, even though they’re declared private. On
the other hand, the caretaker has very limited access to the memento’s fields and methods, which
lets it store mementos in a stack but not tamper with their state.
Implementation based on an intermediate interface
There’s an alternative implementation, suitable for programming languages that don’t
support nested classes (yeah, PHP, I’m talking about you).
1. In the absence of nested classes, you can restrict access to the memento’s fields by
establishing a convention that caretakers can work with a memento only through an explicitly
declared intermediary interface, which would only declare methods related to the memento’s
metadata.
2. On the other hand, originators can work with a memento object directly, accessing fields and
methods declared in the memento class. The downside of this approach is that you need to declare
all members of the memento public.
Implementation with even stricter encapsulation
There’s another implementation which is useful when you don’t want to leave even the
slightest chance of other classes accessing the state of the originator through the
memento.
1. This implementation allows having multiple types of originators and mementos. Each
originator works with a corresponding memento class. Neither originators nor mementos expose
their state to anyone.
2. Caretakers are now explicitly restricted from changing the state stored in mementos.
Moreover, the caretaker class becomes independent from the originator because the restoration
method is now defined in the memento class.
3. Each memento becomes linked to the originator that produced it. The originator passes itself
to the memento’s constructor, along with the values of its state. Thanks to the close relationship
between these classes, a memento can restore the state of its originator, given that the latter has
defined the appropriate setters.
Pseudocode
This example uses the Memento pattern alongside the Command pattern for storing
snapshots of the complex text editor’s state and restoring an earlier state from these
snapshots when needed.
Saving snapshots of the text editor’s state.
The command objects act as caretakers. They fetch the editor’s memento before
executing operations related to commands. When a user attempts to undo the most
recent command, the editor can use the memento stored in that command to revert
itself to the previous state.
The memento class doesn’t declare any public fields, getters or setters. Therefore no
object can alter its contents. Mementos are linked to the editor object that created them.
This lets a memento restore the linked editor’s state by passing the data via setters on
the editor object. Since mementos are linked to specific editor objects, you can make
your app support several independent editor windows with a centralized undo stack.
// The originator holds some important data that may change over
// time. It also defines a method for saving its state inside a
// memento and another method for restoring the state from it.
class Editor is
private field text, curX, curY, selectionWidth
method setText(text) is
this.text = text
method setCursor(x, y) is
this.curX = x
this.curY = y
method setSelectionWidth(width) is
this.selectionWidth = width
method makeBackup() is
backup = editor.createSnapshot()
method undo() is
if (backup != null)
backup.restore()
// ...
Applicability
Use the Memento pattern when you want to produce snapshots of the object’s
state to be able to restore a previous state of the object.
The Memento pattern lets you make full copies of an object’s state, including private
fields, and store them separately from the object. While most people remember this
pattern thanks to the “undo” use case, it’s also indispensable when dealing with
transactions (i.e., if you need to roll back an operation on error).
Use the pattern when direct access to the object’s fields/getters/setters violates
its encapsulation.
The Memento makes the object itself responsible for creating a snapshot of its state.
No other object can read the snapshot, making the original object’s state data safe and
secure.
How to Implement
1. Determine what class will play the role of the originator. It’s important to know
whether the program uses one central object of this type or multiple smaller ones.
2. Create the memento class. One by one, declare a set of fields that mirror the
fields declared inside the originator class.
3. Make the memento class immutable. A memento should accept the data just
once, via the constructor. The class should have no setters.
4. If your programming language supports nested classes, nest the memento inside
the originator. If not, extract a blank interface from the memento class and make all
other objects use it to refer to the memento. You may add some metadata operations to
the interface, but nothing that exposes the originator’s state.
5. Add a method for producing mementos to the originator class. The originator
should pass its state to the memento via one or multiple arguments of the memento’s
constructor.
The return type of the method should be of the interface you extracted in the previous
step (assuming that you extracted it at all). Under the hood, the memento-producing
method should work directly with the memento class.
6. Add a method for restoring the originator’s state to its class. It should accept a
memento object as an argument. If you extracted an interface in the previous step,
make it the type of the parameter. In this case, you need to typecast the incoming object
to the memento class, since the originator needs full access to that object.
8. The link between caretakers and originators may be moved into the memento
class. In this case, each memento must be connected to the originator that had created
it. The restoration method would also move to the memento class. However, this would
all make sense only if the memento class is nested into originator or the originator class
provides sufficient setters for overriding its state.
The app might consume lots of RAM if clients create mementos too often.
Caretakers should track the originator’s lifecycle to be able to destroy obsolete
mementos.
Most dynamic programming languages, such as PHP, Python and JavaScript, can’t
guarantee that the state within the memento stays untouched.
Relations with Other Patterns
You can use Command and Memento together when implementing “undo”. In
this case, commands are responsible for performing various operations over a target
object, while mementos save the state of that object just before a command gets
executed.
Memento in Swift
Memento is a behavioral design pattern that allows making snapshots of an object’s
state and restoring it in future.
The Memento doesn’t compromise the internal structure of the object it works with, as
well as data kept inside the snapshots.
Learn more about Memento
Popularity:
Conceptual Example
This example illustrates the structure of the Memento design pattern and focuses on
the following questions:
After learning about the pattern’s structure it’ll be easier for you to grasp the following
example, based on a real-world Swift use case.
Example.swift: Conceptual example
import XCTest
/// The Originator holds some important state that may change over time. It also
/// defines a method for saving the state inside a memento and another method
/// for restoring the state from it.
class Originator {
/// For the sake of simplicity, the originator's state is stored inside a
/// single variable.
private var state: String
init(state: String) {
self.state = state
print("Originator: My initial state is: \(state)")
}
/// The Originator's business logic may affect its internal state.
/// Therefore, the client should backup the state before launching methods
/// of the business logic via the save() method.
func doSomething() {
print("Originator: I'm doing something important.")
state = generateRandomString()
print("Originator: and my state has changed to: \(state)")
}
/// The Memento interface provides a way to retrieve the memento's metadata,
/// such as creation date or name. However, it doesn't expose the Originator's
/// state.
protocol Memento {
var name: String { get }
var date: Date { get }
}
/// The Concrete Memento contains the infrastructure for storing the
/// Originator's state.
class ConcreteMemento: Memento {
/// The Originator uses this method when restoring its state.
private(set) var state: String
private(set) var date: Date
init(state: String) {
self.state = state
self.date = Date()
}
/// The rest of the methods are used by the Caretaker to display metadata.
var name: String { return state + " " + date.description.suffix(14).prefix(8) }
}
/// The Caretaker doesn't depend on the Concrete Memento class. Therefore, it
/// doesn't have access to the originator's state, stored inside the memento. It
/// works with all mementos via the base Memento interface.
class Caretaker {
init(originator: Originator) {
self.originator = originator
}
func backup() {
print("\nCaretaker: Saving Originator's state...\n")
mementos.append(originator.save())
}
func undo() {
func showHistory() {
print("Caretaker: Here's the list of mementos:\n")
mementos.forEach({ print($0.name) })
}
}
caretaker.backup()
originator.doSomething()
caretaker.backup()
originator.doSomething()
caretaker.backup()
originator.doSomething()
print("\n")
caretaker.showHistory()
Super-duper-super-puper-super. 11:45:44
1923 11:45:44
74FB 11:45:44
Observer
Also known as: Event-Subscriber, Listener
Intent
Observer is a behavioral design pattern that lets you define a subscription mechanism
to notify multiple objects about any events that happen to the object they’re observing.
Problem
Imagine that you have two types of objects: a Customer and a Store. The customer is
very interested in a particular brand of product (say, it’s a new model of the iPhone)
which should become available in the store very soon.
The customer could visit the store every day and check product availability. But while
the product is still en route, most of these trips would be pointless.
Visiting the store vs. sending spam
On the other hand, the store could send tons of emails (which might be considered
spam) to all customers each time a new product becomes available. This would save
some customers from endless trips to the store. At the same time, it’d upset other
customers who aren’t interested in new products.
It looks like we’ve got a conflict. Either the customer wastes time checking product
availability or the store wastes resources notifying the wrong customers.
Solution
The object that has some interesting state is often called subject, but since it’s also
going to notify other objects about the changes to its state, we’ll call it publisher. All
other objects that want to track changes to the publisher’s state are called subscribers.
The Observer pattern suggests that you add a subscription mechanism to the publisher
class so individual objects can subscribe to or unsubscribe from a stream of events
coming from that publisher. Fear not! Everything isn’t as complicated as it sounds. In
reality, this mechanism consists of 1) an array field for storing a list of references to
subscriber objects and 2) several public methods which allow adding subscribers to and
removing them from that list.
A subscription mechanism lets individual objects subscribe to event notifications.
Now, whenever an important event happens to the publisher, it goes over its
subscribers and calls the specific notification method on their objects.
Real apps might have dozens of different subscriber classes that are interested in
tracking events of the same publisher class. You wouldn’t want to couple the publisher
to all of those classes. Besides, you might not even know about some of them
beforehand if your publisher class is supposed to be used by other people.
That’s why it’s crucial that all subscribers implement the same interface and that the
publisher communicates with them only via that interface. This interface should declare
the notification method along with a set of parameters that the publisher can use to pass
some contextual data along with the notification.
Real-World Analogy
The publisher maintains a list of subscribers and knows which magazines they’re
interested in. Subscribers can leave the list at any time when they wish to stop the
publisher sending new magazine issues to them.
Structure
1. The Publisher issues events of interest to other objects. These events occur when the
publisher changes its state or executes some behaviors. Publishers contain a subscription
infrastructure that lets new subscribers join and current subscribers leave the list.
2. When a new event happens, the publisher goes over the subscription list and calls the
notification method declared in the subscriber interface on each subscriber object.
5. Usually, subscribers need some contextual information to handle the update correctly. For
this reason, publishers often pass some context data as arguments of the notification method. The
publisher can pass itself as an argument, letting subscriber fetch any required data directly.
Pseudocode
In this example, the Observer pattern lets the text editor object notify other service
objects about changes in its state.
Notifying objects about events that happen to other objects.
The list of subscribers is compiled dynamically: objects can start or stop listening to
notifications at runtime, depending on the desired behavior of your app.
In this implementation, the editor class doesn’t maintain the subscription list by itself. It
delegates this job to the special helper object devoted to just that. You could upgrade
that object to serve as a centralized event dispatcher, letting any object act as a
publisher.
Adding new subscribers to the program doesn’t require changes to existing publisher
classes, as long as they work with all subscribers through the same interface.
constructor Editor() is
events = new EventManager()
method saveFile() is
file.write()
events.notify("save", file.name)
// ...
method update(filename) is
log.write(replace('%s',filename,message))
Applicability
Use the Observer pattern when changes to the state of one object may require
changing other objects, and the actual set of objects is unknown beforehand or
changes dynamically.
You can often experience this problem when working with classes of the graphical user
interface. For example, you created custom button classes, and you want to let the
clients hook some custom code to your buttons so that it fires whenever a user presses
a button.
The Observer pattern lets any object that implements the subscriber interface subscribe
for event notifications in publisher objects. You can add the subscription mechanism to
your buttons, letting the clients hook up their custom code via custom subscriber
classes.
Use the pattern when some objects in your app must observe others, but only for
a limited time or in specific cases.
The subscription list is dynamic, so subscribers can join or leave the list whenever they
need to.
How to Implement
1. Look over your business logic and try to break it down into two parts: the core
functionality, independent from other code, will act as the publisher; the rest will turn into
a set of subscriber classes.
2. Declare the subscriber interface. At a bare minimum, it should declare a
single update method.
3. Declare the publisher interface and describe a pair of methods for adding a
subscriber object to and removing it from the list. Remember that publishers must work
with subscribers only via the subscriber interface.
4. Decide where to put the actual subscription list and the implementation of
subscription methods. Usually, this code looks the same for all types of publishers, so
the obvious place to put it is in an abstract class derived directly from the publisher
interface. Concrete publishers extend that class, inheriting the subscription behavior.
But there’s another option. Upon receiving a notification, the subscriber can fetch any
data directly from the notification. In this case, the publisher must pass itself via the
update method. The less flexible option is to link a publisher to the subscriber
permanently via the constructor.
7. The client must create all necessary subscribers and register them with proper
publishers.
When you’re confused, remember that you can implement the Mediator pattern in other
ways. For example, you can permanently link all the components to the same mediator
object. This implementation won’t resemble Observer but will still be an instance of the
Mediator pattern.
Now imagine a program where all components have become publishers, allowing
dynamic connections between each other. There won’t be a centralized mediator object,
only a distributed set of observers.
Observer in Swift
Observer is a behavioral design pattern that allows some objects to notify other objects about
changes in their state.
The Observer pattern provides a way to subscribe and unsubscribe to and from these events for
any object that implements a subscriber interface.
Learn more about Observer
Usage examples: The Observer pattern is pretty common in Swift code, especially in the GUI
components. It provides a way to react to events happening in other objects without coupling to
their classes.
Identification: The pattern can be recognized by subscription methods, that store objects in a list
and by calls to the update method issued to objects in that list.
Conceptual Example
This example illustrates the structure of the Observer design pattern and focuses on the
following questions:
After learning about the pattern’s structure it’ll be easier for you to grasp the following example,
based on a real-world Swift use case.
Example.swift: Conceptual example
import XCTest
/// The Subject owns some important state and notifies observers when the state
/// changes.
class Subject {
/// For the sake of simplicity, the Subject's state, essential to all
/// subscribers, is stored in this variable.
var state: Int = { return Int(arc4random_uniform(10)) }()
/// @var array List of subscribers. In real life, the list of subscribers
/// can be stored more comprehensively (categorized by event type, etc.).
private lazy var observers = [Observer]()
/// Usually, the subscription logic is only a fraction of what a Subject can
/// really do. Subjects commonly hold some important business logic, that
/// triggers a notification method whenever something important is about to
/// happen (or after it).
func someBusinessLogic() {
print("\nSubject: I'm doing something important.\n")
state = Int(arc4random_uniform(10))
print("Subject: My state has just changed to: \(state)\n")
notify()
}
}
/// The Observer protocol declares the update method, used by subjects.
protocol Observer: class {
/// Concrete Observers react to the updates issued by the Subject they had been
/// attached to.
class ConcreteObserverA: Observer {
if subject.state < 3 {
print("ConcreteObserverA: Reacted to the event.\n")
}
}
}
if subject.state >= 3 {
print("ConcreteObserverB: Reacted to the event.\n")
}
}
}
func testObserverConceptual() {
subject.attach(observer1)
subject.attach(observer2)
subject.someBusinessLogic()
subject.someBusinessLogic()
subject.detach(observer2)
subject.someBusinessLogic()
}
}
Output.txt: Execution result
Subject: Attached an observer.
cartManager.add(subscriber: navigationBar)
cartManager.add(subscriber: cartVC)
let apple = Food(id: 111, name: "Apple", price: 10, calories: 20)
cartManager.add(product: apple)
let tShirt = Clothes(id: 222, name: "T-shirt", price: 200, size: "L")
cartManager.add(product: tShirt)
cartManager.remove(product: apple)
}
}
protocol Product {
extension Product {
class CartManager {