Design Pattern
Design Pattern
You can’t just find a pattern and copy it into your program, the way you can with off-the-
shelf functions or libraries. The pattern is not a specific piece of code, but a general
concept for solving a particular problem. You can follow the pattern details and
implement a solution that suits the realities of your own program.
Patterns are often confused with algorithms, because both concepts describe typical
solutions to some known problems. While an algorithm always defines a clear set of
actions that can achieve some goal, a pattern is a more high-level description of a
solution. The code of the same pattern applied to two different programs may be
different.
An analogy to an algorithm is a cooking recipe: both have clear steps to achieve a goal.
On the other hand, a pattern is more like a blueprint: you can see what the result and its
features are, but the exact order of implementation is up to you.
Intent of the pattern briefly describes both the problem and the solution.
Motivation further explains the problem and the solution the pattern makes possible.
Structure of classes shows each part of the pattern and how they are related.
Code example in one of the popular programming languages makes it easier to grasp
the idea behind the pattern.
History of patterns
Who invented patterns? That’s a good, but not a very accurate, question. Design
patterns aren’t obscure, sophisticated concepts—quite the opposite. Patterns are typical
solutions to common problems in object-oriented design. When a solution gets repeated
over and over in various projects, someone eventually puts a name to it and describes
the solution in detail. That’s basically how a pattern gets discovered.
The concept of patterns was first described by Christopher Alexander in A Pattern
Language: Towns, Buildings, Construction. The book describes a “language” for
designing the urban environment. The units of this language are patterns. They may
describe how high windows should be, how many levels a building should have, how
large green areas in a neighborhood are supposed to be, and so on.
The idea was picked up by four authors: Erich Gamma, John Vlissides, Ralph Johnson,
and Richard Helm. In 1994, they published Design Patterns: Elements of Reusable
Object-Oriented Software, in which they applied the concept of design patterns to
programming. The book featured 23 patterns solving various problems of object-
oriented design and became a best-seller very quickly. Due to its lengthy name, people
started to call it “the book by the gang of four” which was soon shortened to simply “the
GoF book”.
Since then, dozens of other object-oriented patterns have been discovered. The
“pattern approach” became very popular in other programming fields, so lots of other
patterns now exist outside of object-oriented design as well.
Design patterns are a toolkit of tried and tested solutions to common problems
in software design. Even if you never encounter these problems, knowing
patterns is still useful because it teaches you how to solve all sorts of problems
using principles of object-oriented design.
Design patterns define a common language that you and your teammates can
use to communicate more efficiently. You can say, “Oh, just use a Singleton for
that,” and everyone will understand the idea behind your suggestion. No need to
explain what a singleton is if you know the pattern and its name.
Classification of patterns
Design patterns differ by their complexity, level of detail and scale of applicability to the entire
system being designed. I like the analogy to road construction: you can make an intersection
safer by either installing some traffic lights or building an entire multi-level interchange with
underground passages for pedestrians.
The most basic and low-level patterns are often called idioms. They usually apply only to a
single programming language.
The most universal and high-level patterns are architectural patterns. Developers can implement
these patterns in virtually any language. Unlike other patterns, they can be used to design the
architecture of an entire application.
In addition, all patterns can be categorized by their intent, or purpose. This book covers three
main groups of patterns:
Structural patterns explain how to assemble objects and classes into larger structures,
while keeping the structures flexible and efficient.
The client code has to work with both factories and products via their respective
abstract interfaces. This lets you change the type of a factory that you pass to the client
code, as well as the product variant that the client code receives, without breaking the
actual client code.
The client shouldn’t care about the concrete class of the factory it works with.
Say the client wants a factory to produce a chair. The client doesn’t have to be aware of
the factory’s class, nor does it matter what kind of chair it gets. Whether it’s a Modern
model or a Victorian-style chair, the client must treat all chairs in the same manner,
using the abstract Chair interface. With this approach, the only thing that the client
knows about the chair is that it implements the sitOn method in some way. Also,
whichever variant of the chair is returned, it’ll always match the type of sofa or coffee
table produced by the same factory object.
There’s one more thing left to clarify: if the client is only exposed to the abstract
interfaces, what creates the actual factory objects? Usually, the application creates a
concrete factory object at the initialization stage. Just before that, the app must select
the factory type depending on the configuration or the environment settings.
Structure
The Abstract Factory interface declares a set of creation methods that the client code
can use to produce different types of UI elements. Concrete factories correspond to
specific operating systems and create the UI elements that match that particular OS.
It works like this: when an application launches, it checks the type of the current
operating system. The app uses this information to create a factory object from a class
that matches the operating system. The rest of the code uses this factory to create UI
elements. This prevents the wrong elements from being created.
With this approach, the client code doesn’t depend on concrete classes of factories and
UI elements as long as it works with these objects via their abstract interfaces. This also
lets the client code support other factories or UI elements that you might add in the
future.
As a result, you don’t need to modify the client code each time you add a new variation
of UI elements to your app. You just have to create a new factory class that produces
these elements and slightly modify the app’s initialization code so it selects that class
when appropriate.
The Abstract Factory provides you with an interface for creating objects from each
class of the product family. As long as your code creates objects via this interface, you
don’t have to worry about creating the wrong variant of a product which doesn’t match
the products already created by your app.
Consider implementing the Abstract Factory when you have a class with a set
of Factory Methods that blur its primary responsibility.
How to Implement
1. Map out a matrix of distinct product types versus variants of these products.
2. Declare abstract product interfaces for all product types. Then make all concrete
product classes implement these interfaces.
3. Declare the abstract factory interface with a set of creation methods for all
abstract products.
4. Implement a set of concrete factory classes, one for each product variant.
5. Create factory initialization code somewhere in the app. It should instantiate one
of the concrete factory classes, depending on the application configuration or the
current environment. Pass this factory object to all classes that construct products.
6. Scan through the code and find all direct calls to product constructors. Replace
them with calls to the appropriate creation method on the factory object.
Pros and Cons
You can be sure that the products you’re getting from a factory are compatible with
each other.
You avoid tight coupling between concrete products and client code.
Single Responsibility Principle. You can extract the product creation code into one
place, making the code easier to support.
Open/Closed Principle. You can introduce new variants of products without breaking
existing client code.
The code may become more complicated than it should be, since a lot of new interfaces
and classes are introduced along with the pattern.
Relations with Other Patterns
Abstract Factory classes are often based on a set of Factory Methods, but you
can also use Prototype to compose the methods on these classes.
Builder
Intent
Builder is a creational design pattern that lets you construct complex objects step by
step. The pattern allows you to produce different types and representations of an object
using the same construction code.
Problem
Imagine a complex object that requires laborious, step-by-step initialization of many
fields and nested objects. Such initialization code is usually buried inside a monstrous
constructor with lots of parameters. Or even worse: scattered all over the client code.
You might make the program too complex by creating a subclass for every possible
configuration of an object.
For example, let’s think about how to create a House object. To build a simple house, you
need to construct four walls and a floor, install a door, fit a pair of windows, and build a
roof. But what if you want a bigger, brighter house, with a backyard and other goodies
(like a heating system, plumbing, and electrical wiring)?
The simplest solution is to extend the base House class and create a set of subclasses to
cover all combinations of the parameters. But eventually you’ll end up with a
considerable number of subclasses. Any new parameter, such as the porch style, will
require growing this hierarchy even more.
There’s another approach that doesn’t involve breeding subclasses. You can create a
giant constructor right in the base House class with all possible parameters that control
the house object. While this approach indeed eliminates the need for subclasses, it
creates another problem.
The constructor with lots of parameters has its downside: not all the parameters are
needed at all times.
In most cases most of the parameters will be unused, making the constructor calls
pretty ugly. For instance, only a fraction of houses have swimming pools, so the
parameters related to swimming pools will be useless nine times out of ten.
Solution
The Builder pattern suggests that you extract the object construction code out of its own
class and move it to separate objects called builders.
The Builder pattern lets you construct complex objects step by step. The Builder doesn’t
allow other objects to access the product while it’s being built.
The pattern organizes object construction into a set of steps
(buildWalls, buildDoor, etc.). To create an object, you execute a series of these steps on
a builder object. The important part is that you don’t need to call all of the steps. You
can call only those steps that are necessary for producing a particular configuration of
an object.
Some of the construction steps might require different implementation when you need to
build various representations of the product. For example, walls of a cabin may be built
of wood, but the castle walls must be built with stone.
In this case, you can create several different builder classes that implement the same
set of building steps, but in a different manner. Then you can use these builders in the
construction process (i.e., an ordered set of calls to the building steps) to produce
different kinds of objects.
Director
You can go further and extract a series of calls to the builder steps you use to construct
a product into a separate class called director. The director class defines the order in
which to execute the building steps, while the builder provides the implementation for
those steps.
The director knows which building steps to execute to get a working product.
Having a director class in your program isn’t strictly necessary. You can always call the
building steps in a specific order directly from the client code. However, the director
class might be a good place to put various construction routines so you can reuse them
across your program.
In addition, the director class completely hides the details of product construction from
the client code. The client only needs to associate a builder with a director, launch the
construction with the director, and get the result from the builder.
Structure
1. The Builder interface declares product construction steps that are common to all types of
builders.
4. The Director class defines the order in which to call construction steps, so you can create
and reuse specific configurations of products.
5. The Client must associate one of the builder objects with the director. Usually, it’s done just
once, via parameters of the director’s constructor. Then the director uses that builder object for all
further construction. However, there’s an alternative approach for when the client passes the builder
object to the production method of the director. In this case, you can use a different builder each
time you produce something with the director.
Pseudocode
This example of the Builder pattern illustrates how you can reuse the same object
construction code when building different types of products, such as cars, and create
the corresponding manuals for them.
The example of step-by-step construction of cars and the user guides that fit those
car models.
A car is a complex object that can be constructed in a hundred different ways. Instead
of bloating the Car class with a huge constructor, we extracted the car assembly code
into a separate car builder class. This class has a set of methods for configuring various
parts of a car.
If the client code needs to assemble a special, fine-tuned model of a car, it can work
with the builder directly. On the other hand, the client can delegate the assembly to the
director class, which knows how to use a builder to construct several of the most
popular models of cars.
You might be shocked, but every car needs a manual (seriously, who reads them?).
The manual describes every feature of the car, so the details in the manuals vary
across the different models. That’s why it makes sense to reuse an existing construction
process for both real cars and their respective manuals. Of course, building a manual
isn’t the same as building a car, and that’s why we must provide another builder class
that specializes in composing manuals. This class implements the same building
methods as its car-building sibling, but instead of crafting car parts, it describes them.
By passing these builders to the same director object, we can construct either a car or a
manual.
The final part is fetching the resulting object. A metal car and a paper manual, although
related, are still very different things. We can’t place a method for fetching results in the
director without coupling the director to concrete product classes. Hence, we obtain the
result of the construction from the builder which performed the job.
// Using the Builder pattern makes sense only when your products
// are quite complex and require extensive configuration. The
// following two products are related, although they don't have
// a common interface.
class Car is
// A car can have a GPS, trip computer and some number of
// seats. Different models of cars (sports car, SUV,
// cabriolet) might have different features installed or
// enabled.
class Manual is
// Each car should have a user manual that corresponds to
// the car's configuration and describes all its features.
method setEngine(...) is
// Install a given engine.
method setTripComputer(...) is
// Install a trip computer.
method setGPS(...) is
// Install a global positioning system.
constructor CarManualBuilder() is
this.reset()
method reset() is
this.manual = new Manual()
method setSeats(...) is
// Document car seat features.
method setEngine(...) is
// Add engine instructions.
method setTripComputer(...) is
// Add trip computer instructions.
method setGPS(...) is
// Add GPS instructions.
method getProduct():Manual is
// Return the manual and reset the builder.
method makeCar() is
director = new Director()
CarBuilder builder = new CarBuilder()
director.constructSportsCar(builder)
Car car = builder.getProduct()
Say you have a constructor with ten optional parameters. Calling such a beast is very
inconvenient; therefore, you overload the constructor and create several shorter
versions with fewer parameters. These constructors still refer to the main one, passing
some default values into any omitted parameters.
class Pizza {
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean cheese, boolean pepperoni) { ... }
// ...
Creating such a monster is only possible in languages that support method overloading,
such as C# or Java.
The Builder pattern lets you build objects step by step, using only those steps that you
really need. After implementing the pattern, you don’t have to cram dozens of
parameters into your constructors anymore.
Use the Builder pattern when you want your code to be able to create different
representations of some product (for example, stone and wooden houses).
The Builder pattern can be applied when construction of various representations of the
product involves similar steps that differ only in the details.
The base builder interface defines all possible construction steps, and concrete builders
implement these steps to construct particular representations of the product.
Meanwhile, the director class guides the order of construction.
The Builder pattern lets you construct products step-by-step. You could defer execution
of some steps without breaking the final product. You can even call steps recursively,
which comes in handy when you need to build an object tree.
A builder doesn’t expose the unfinished product while running construction steps. This
prevents the client code from fetching an incomplete result.
How to Implement
1. Make sure that you can clearly define the common construction steps for building
all available product representations. Otherwise, you won’t be able to proceed with
implementing the pattern.
3. Create a concrete builder class for each of the product representations and
implement their construction steps.
Don’t forget about implementing a method for fetching the result of the construction. The
reason why this method can’t be declared inside the builder interface is that various
builders may construct products that don’t have a common interface. Therefore, you
don’t know what would be the return type for such a method. However, if you’re dealing
with products from a single hierarchy, the fetching method can be safely added to the
base interface.
5. The client code creates both the builder and the director objects. Before
construction starts, the client must pass a builder object to the director. Usually, the
client does this only once, via parameters of the director’s constructor. The director uses
the builder object in all further construction. There’s an alternative approach, where the
builder is passed directly to the construction method of the director.
6. The construction result can be obtained directly from the director only if all
products follow the same interface. Otherwise, the client should fetch the result from the
builder.
You can construct objects step-by-step, defer construction steps or run steps
recursively.
You can reuse the same construction code when building various representations of
products.
Single Responsibility Principle. You can isolate complex construction code from the
business logic of the product.
The overall complexity of the code increases since the pattern requires creating multiple
new classes.
Relations with Other Patterns
You can combine Builder with Bridge: the director class plays the role of the
abstraction, while different builders act as implementations.
Factory Method
Also known as: Virtual Constructor
Intent
Factory Method is a creational design pattern that provides an interface for creating
objects in a superclass, but allows subclasses to alter the type of objects that will
be created.
Problem
Imagine that you’re creating a logistics management application. The first version of
your app can only handle transportation by trucks, so the bulk of your code lives inside
the Truck class.
After a while, your app becomes pretty popular. Each day you receive dozens of
requests from sea transportation companies to incorporate sea logistics into the app.
Adding a new class to the program isn’t that simple if the rest of the code is already
coupled to existing classes.
Great news, right? But how about the code? At present, most of your code is coupled to
the Truck class. Adding Ships into the app would require making changes to the entire
codebase. Moreover, if later you decide to add another type of transportation to the app,
you will probably need to make all of these changes again.
As a result, you will end up with pretty nasty code, riddled with conditionals that switch
the app’s behavior depending on the class of transportation objects.
Solution
The Factory Method pattern suggests that you replace direct object construction calls
(using the new operator) with calls to a special factory method.
Don’t worry: the objects are still created via the new operator, but it’s being called from
within the factory method. Objects returned by a factory method are often referred to
as products.
Subclasses can alter the class of objects being returned by the factory method.
At first glance, this change may look pointless: we just moved the constructor call from
one part of the program to another. However, consider this: now you can override the
factory method in a subclass and change the class of products being created by the
method.
There’s a slight limitation though: subclasses may return different types of products only
if these products have a common base class or interface. Also, the factory method in
the base class should have its return type declared as this interface.
All products must follow the same interface.
For example, both Truck and Ship classes should implement the Transport interface,
which declares a method called deliver. Each class implements this method differently:
trucks deliver cargo by land, ships deliver cargo by sea. The factory method in
the RoadLogistics class returns truck objects, whereas the factory method in
the SeaLogistics class returns ships.
As long as all product classes implement a common interface, you can pass their
objects to the client code without breaking it.
The code that uses the factory method (often called the client code) doesn’t see a
difference between the actual products returned by various subclasses. The client treats
all the products as abstract Transport. The client knows that all transport objects are
supposed to have the deliver method, but exactly how it works isn’t important to the
client.
Structure
1. The Product declares the interface, which is common to all objects that can be produced by
the creator and its subclasses.
3. The Creator class declares the factory method that returns new product objects. It’s
important that the return type of this method matches the product interface.
You can declare the factory method as abstract to force all subclasses to implement their own
versions of the method. As an alternative, the base factory method can return some default product
type.
Note, despite its name, product creation is not the primary responsibility of the creator. Usually, the creator class
already has some core business logic related to products. The factory method helps to decouple this logic from the
concrete product classes. Here is an analogy: a large software development company can have a training
department for programmers. However, the primary function of the company as a whole is still writing code, not
producing programmers.
4. Concrete Creators override the base factory method so it returns a different type of product.
Note that the factory method doesn’t have to create new instances all the time. It can also return
existing objects from a cache, an object pool, or another source.
Pseudocode
This example illustrates how the Factory Method can be used for creating cross-
platform UI elements without coupling the client code to concrete UI classes.
When the factory method comes into play, you don’t need to rewrite the logic of the
dialog for each operating system. If we declare a factory method that produces buttons
inside the base dialog class, we can later create a dialog subclass that returns
Windows-styled buttons from the factory method. The subclass then inherits most of the
dialog’s code from the base class, but, thanks to the factory method, can render
Windows-looking buttons on the screen.
For this pattern to work, the base dialog class must work with abstract buttons: a base
class or an interface that all concrete buttons follow. This way the dialog’s code remains
functional, whichever type of buttons it works with.
Of course, you can apply this approach to other UI elements as well. However, with
each new factory method you add to the dialog, you get closer to the Abstract
Factory pattern. Fear not, we’ll talk about this pattern later.
class Application is
field dialog: Dialog
The Factory Method separates product construction code from the code that actually
uses the product. Therefore it’s easier to extend the product construction code
independently from the rest of the code.
For example, to add a new product type to the app, you’ll only need to create a new
creator subclass and override the factory method in it.
Use the Factory Method when you want to provide users of your library or
framework with a way to extend its internal components.
Inheritance is probably the easiest way to extend the default behavior of a library or
framework. But how would the framework recognize that your subclass should be used
instead of a standard component?
The solution is to reduce the code that constructs components across the framework
into a single factory method and let anyone override this method in addition to extending
the component itself.
Let’s see how that would work. Imagine that you write an app using an open source UI
framework. Your app should have round buttons, but the framework only provides
square ones. You extend the standard Button class with a glorious RoundButton subclass.
But now you need to tell the main UIFramework class to use the new button subclass
instead of a default one.
Use the Factory Method when you want to save system resources by reusing
existing objects instead of rebuilding them each time.
You often experience this need when dealing with large, resource-intensive objects
such as database connections, file systems, and network resources.
1. First, you need to create some storage to keep track of all of the created objects.
2. When someone requests an object, the program should look for a free object inside that
pool.
3. … and then return it to the client code.
4. If there are no free objects, the program should create a new one (and add it to the
pool).
That’s a lot of code! And it must all be put into a single place so that you don’t pollute
the program with duplicate code.
Probably the most obvious and convenient place where this code could be placed is the
constructor of the class whose objects we’re trying to reuse. However, a constructor
must always return new objects by definition. It can’t return existing instances.
Therefore, you need to have a regular method capable of creating new objects as well
as reusing existing ones. That sounds very much like a factory method.
How to Implement
1. Make all products follow the same interface. This interface should declare
methods that make sense in every product.
2. Add an empty factory method inside the creator class. The return type of the
method should match the common product interface.
3. In the creator’s code find all references to product constructors. One by one,
replace them with calls to the factory method, while extracting the product creation code
into the factory method.
You might need to add a temporary parameter to the factory method to control the type
of returned product.
At this point, the code of the factory method may look pretty ugly. It may have a
large switch operator that picks which product class to instantiate. But don’t worry, we’ll
fix it soon enough.
4. Now, create a set of creator subclasses for each type of product listed in the
factory method. Override the factory method in the subclasses and extract the
appropriate bits of construction code from the base method.
5. If there are too many product types and it doesn’t make sense to create
subclasses for all of them, you can reuse the control parameter from the base class in
subclasses.
For instance, imagine that you have the following hierarchy of classes: the
base Mail class with a couple of subclasses: AirMail and GroundMail;
the Transport classes are Plane, Truck and Train. While the AirMail class only
uses Plane objects, GroundMail may work with both Truck and Train objects. You can
create a new subclass (say TrainMail) to handle both cases, but there’s another option.
The client code can pass an argument to the factory method of the GroundMail class to
control which product it wants to receive.
6. If, after all of the extractions, the base factory method has become empty, you
can make it abstract. If there’s something left, you can make it a default behavior of the
method.
You avoid tight coupling between the creator and the concrete products.
Single Responsibility Principle. You can move the product creation code into one place
in the program, making the code easier to support.
Open/Closed Principle. You can introduce new types of products into the program
without breaking existing client code.
The code may become more complicated since you need to introduce a lot of new
subclasses to implement the pattern. The best case scenario is when you’re introducing the
pattern into an existing hierarchy of creator classes.
Relations with Other Patterns
Abstract Factory classes are often based on a set of Factory Methods, but you
can also use Prototype to compose the methods on these classes.
You can use Factory Method along with Iterator to let collection subclasses
return different types of iterators that are compatible with the collections.
Prototype
Also known as: Clone
Intent
Prototype is a creational design pattern that lets you copy existing objects without
making your code dependent on their classes.
Problem
Say you have an object, and you want to create an exact copy of it. How would you do
it? First, you have to create a new object of the same class. Then you have to go
through all the fields of the original object and copy their values over to the new object.
Nice! But there’s a catch. Not all objects can be copied that way because some of the
object’s fields may be private and not visible from outside of the object itself.
There’s one more problem with the direct approach. Since you have to know the
object’s class to create a duplicate, your code becomes dependent on that class. If the
extra dependency doesn’t scare you, there’s another catch. Sometimes you only know
the interface that the object follows, but not its concrete class, when, for example, a
parameter in a method accepts any objects that follow some interface.
Solution
The Prototype pattern delegates the cloning process to the actual objects that are being
cloned. The pattern declares a common interface for all objects that support cloning.
This interface lets you clone an object without coupling your code to the class of that
object. Usually, such an interface contains just a single clone method.
An object that supports cloning is called a prototype. When your objects have dozens of
fields and hundreds of possible configurations, cloning them might serve as an
alternative to subclassing.
3. The Client can produce a copy of any object that follows the prototype interface.
Prototype registry implementation
// Base prototype.
abstract class Shape is
field X: int
field Y: int
field color: string
// A regular constructor.
constructor Shape() is
// ...
method clone():Shape is
return new Rectangle(this)
method clone():Shape is
return new Circle(this)
constructor Application() is
Circle circle = new Circle()
circle.X = 10
circle.Y = 10
circle.radius = 20
shapes.add(circle)
method businessLogic() is
// Prototype rocks because it lets you produce a copy of
// an object without knowing anything about its type.
Array shapesCopy = new Array of Shapes.
This happens a lot when your code works with objects passed to you from 3rd-party
code via some interface. The concrete classes of these objects are unknown, and you
couldn’t depend on them even if you wanted to.
The Prototype pattern provides the client code with a general interface for working with
all objects that support cloning. This interface makes the client code independent from
the concrete classes of objects that it clones.
Use the pattern when you want to reduce the number of subclasses that only
differ in the way they initialize their respective objects. Somebody could have
created these subclasses to be able to create objects with a specific
configuration.
The Prototype pattern lets you use a set of pre-built objects, configured in various
ways, as prototypes.
Instead of instantiating a subclass that matches some configuration, the client can
simply look for an appropriate prototype and clone it.
How to Implement
1. Create the prototype interface and declare the clone method in it. Or just add the
method to all classes of an existing class hierarchy, if you have one.
2. A prototype class must define the alternative constructor that accepts an object
of that class as an argument. The constructor must copy the values of all fields defined
in the class from the passed object into the newly created instance. If you’re changing a
subclass, you must call the parent constructor to let the superclass handle the cloning of
its private fields.
If your programming language doesn’t support method overloading, you may define a
special method for copying the object data. The constructor is a more convenient place
to do this because it delivers the resulting object right after you call the new operator.
3. The cloning method usually consists of just one line: running a new operator with
the prototypical version of the constructor. Note, that every class must explicitly override
the cloning method and use its own class name along with the new operator. Otherwise,
the cloning method may produce an object of a parent class.
You can implement the registry as a new factory class or put it in the base prototype
class with a static method for fetching the prototype. This method should search for a
prototype based on search criteria that the client code passes to the method. The
criteria might either be a simple string tag or a complex set of search parameters. After
the appropriate prototype is found, the registry should clone it and return the copy to the
client.
Finally, replace the direct calls to the subclasses’ constructors with calls to the factory
method of the prototype registry.
Cloning complex objects that have circular references might be very tricky.
Relations with Other Patterns
Abstract Factory classes are often based on a set of Factory Methods, but you
can also use Prototype to compose the methods on these classes.
Singleton
Intent
Singleton is a creational design pattern that lets you ensure that a class has only one
instance, while providing a global access point to this instance.
Problem
The Singleton pattern solves two problems at the same time, violating the Single
Responsibility Principle:
1. Ensure that a class has just a single instance. Why would anyone want to
control how many instances a class has? The most common reason for this is to
control access to some shared resource—for example, a database or a file.
Here’s how it works: imagine that you created an object, but after a while decided
to create a new one. Instead of receiving a fresh object, you’ll get the one you
already created.
Clients may not even realize that they’re working with the same object all the time.
Just like a global variable, the Singleton pattern lets you access some object
from anywhere in the program. However, it also protects that instance from being
overwritten by other code.
There’s another side to this problem: you don’t want the code that solves
problem #1 to be scattered all over your program. It’s much better to have it
within one class, especially if the rest of your code already depends on it.
Nowadays, the Singleton pattern has become so popular that people may call
something a singleton even if it solves just one of the listed problems.
Solution
All implementations of the Singleton have these two steps in common:
Make the default constructor private, to prevent other objects from using
the new operator with the Singleton class.
Create a static creation method that acts as a constructor. Under the hood, this method
calls the private constructor to create an object and saves it in a static field. All following
calls to this method return the cached object.
If your code has access to the Singleton class, then it’s able to call the Singleton’s static
method. So whenever that method is called, the same object is always returned.
Real-World Analogy
The government is an excellent example of the Singleton pattern. A country can have
only one official government. Regardless of the personal identities of the individuals
who form governments, the title, “The Government of X”, is a global point of access that
identifies the group of people in charge.
Structure
The Singleton’s constructor should be hidden from the client code. Calling the getInstance method
should be the only way of getting the Singleton object.
Pseudocode
In this example, the database connection class acts as a Singleton. This class doesn’t
have a public constructor, so the only way to get its object is to call
the getInstance method. This method caches the first created object and returns it in all
subsequent calls.
class Application is
method main() is
Database foo = Database.getInstance()
foo.query("SELECT ...")
// ...
Database bar = Database.getInstance()
bar.query("SELECT ...")
// The variable `bar` will contain the same object as
// the variable `foo`.
Applicability
Use the Singleton pattern when a class in your program should have just a single
instance available to all clients; for example, a single database object shared by
different parts of the program.
The Singleton pattern disables all other means of creating objects of a class except for
the special creation method. This method either creates a new object or returns an
existing one if it has already been created.
Use the Singleton pattern when you need stricter control over global variables.
Unlike global variables, the Singleton pattern guarantees that there’s just one instance
of a class. Nothing, except for the Singleton class itself, can replace the cached
instance.
Note that you can always adjust this limitation and allow creating any number of
Singleton instances. The only piece of code that needs changing is the body of
the getInstance method.
How to Implement
1. Add a private static field to the class for storing the singleton instance.
2. Declare a public static creation method for getting the singleton instance.
3. Implement “lazy initialization” inside the static method. It should create a new
object on its first call and put it into the static field. The method should always return that
instance on all subsequent calls.
4. Make the constructor of the class private. The static method of the class will still
be able to call the constructor, but not the other objects.
5. Go over the client code and replace all direct calls to the singleton’s constructor
with calls to its static creation method.
Violates the Single Responsibility Principle. The pattern solves two problems at the
time.
The Singleton pattern can mask bad design, for instance, when the components of the
program know too much about each other.
The pattern requires special treatment in a multithreaded environment so that multiple
threads won’t create a singleton object several times.
It may be difficult to unit test the client code of the Singleton because many test
frameworks rely on inheritance when producing mock objects. Since the constructor of the
singleton class is private and overriding static methods is impossible in most languages, you will
need to think of a creative way to mock the singleton. Or just don’t write the tests. Or don’t use
the Singleton pattern.
Abstract Factory defines an interface for creating all distinct products but leaves the
actual product creation to concrete factory classes. Each factory type corresponds to a
certain product variety.
The client code calls the creation methods of a factory object instead of creating
products directly with a constructor call (new operator). Since a factory corresponds to a
single product variant, all its products will be compatible.
Client code works with factories and products only through their abstract interfaces. This
lets the client code work with any product variants, created by the factory object. You
just create a new concrete factory class and pass it to the client code.
If you can’t figure out the difference between various factory patterns and concepts,
then read our Factory Comparison.
Learn more about Abstract Factory
Popularity:
Usage examples: The Abstract Factory pattern is pretty common in Swift code. Many
frameworks and libraries use it to provide a way to extend and customize their standard
components.
Identification: The pattern is easy to recognize by methods, which return a factory
object. Then, the factory is used for creating specific sub-components.
Conceptual Example
This example illustrates the structure of the Abstract Factory design pattern. It focuses
on answering these 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 Abstract Factory protocol declares a set of methods that return
/// different abstract products. These products are called a family and are
/// related by a high-level theme or concept. Products of one family are usually
/// able to collaborate among themselves. A family of products may have several
/// variants, but the products of one variant are incompatible with products of
/// another.
protocol AbstractFactory {
/// Each distinct product of a product family should have a base protocol. All
/// variants of the product must implement this protocol.
protocol AbstractProductA {
/// The base protocol of another product. All products can interact with each
/// other, but proper interaction is possible only between products of the same
/// concrete variant.
protocol AbstractProductB {
/// This variant, Product B1, is only able to work correctly with the
/// variant, Product A1. Nevertheless, it accepts any instance of
/// AbstractProductA as an argument.
func anotherUsefulFunctionB(collaborator: AbstractProductA) -> String {
let result = collaborator.usefulFunctionA()
return "The result of the B1 collaborating with the (\(result))"
}
}
/// This variant, Product B2, is only able to work correctly with the
/// variant, Product A2. Nevertheless, it accepts any instance of
/// AbstractProductA as an argument.
func anotherUsefulFunctionB(collaborator: AbstractProductA) -> String {
let result = collaborator.usefulFunctionA()
return "The result of the B2 collaborating with the (\(result))"
}
}
/// The client code works with factories and products only through abstract
/// types: AbstractFactory and AbstractProduct. This lets you pass any factory
/// or product subclass to the client code without breaking it.
class Client {
// ...
static func someClientCode(factory: AbstractFactory) {
let productA = factory.createProductA()
let productB = factory.createProductB()
print(productB.usefulFunctionB())
print(productB.anotherUsefulFunctionB(collaborator: productA))
}
// ...
}
func testAbstractFactoryConceptual() {
/// The client code can work with any concrete factory class.
print("Client: Testing the same client code with the second factory type:")
Client.someClientCode(factory: ConcreteFactory2())
}
}
Output.txt: Execution result
Client: Testing client code with the first factory type:
The result of the product B1.
The result of the B1 collaborating with the (The result of the product A1.)
Client: Testing the same client code with the second factory type:
The result of the product B2.
The result of the B2 collaborating with the (The result of the product A2.)
Real World Example
Example.swift: Real world example
import Foundation
import UIKit
import XCTest
enum AuthType {
case login
case signUp
}
protocol AuthViewFactory {
protocol AuthView {
/// The handler will be connected for actions of buttons of this view.
var authHandler: AuthView.AuthAction?
/// The handler will be connected for actions of buttons of this view.
var authHandler: AuthView.AuthAction?
/// The handler will be connected for actions of buttons of this view.
var authHandler: AuthView.AuthAction?
/// The handler will be connected for actions of buttons of this view.
var authHandler: AuthView.AuthAction?
init(contentView: AuthView) {
self.contentView = contentView
super.init(nibName: nil, bundle: nil)
}
init(factoryType: AuthViewFactory.Type) {
self.factoryType = factoryType
}
func presentLogin() {
let controller = factoryType.authController(for: .login)
navigationController.pushViewController(controller, animated: true)
}
func presentSignUp() {
let controller = factoryType.authController(for: .signUp)
navigationController.pushViewController(controller, animated: true)
}
func testFactoryMethodRealWorld() {
#if teacherMode
let clientCode = ClientCode(factoryType: TeacherAuthViewFactory.self)
#else
let clientCode = ClientCode(factoryType: StudentAuthViewFactory.self)
#endif
Builder in Swift
Builder is a creational design pattern, which allows constructing complex objects step
by step.
Unlike other creational patterns, Builder doesn’t require products to have a common
interface. That makes it possible to produce different products using the same
construction process.
Learn more about Builder
Popularity:
Conceptual Example
This example illustrates the structure of the Builder 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 Builder interface specifies methods for creating the different parts of
/// the Product objects.
protocol Builder {
func producePartA()
func producePartB()
func producePartC()
}
/// The Concrete Builder classes follow the Builder interface and provide
/// specific implementations of the building steps. Your program may have
/// several variations of Builders, implemented differently.
class ConcreteBuilder1: Builder {
/// A fresh builder instance should contain a blank product object, which is
/// used in further assembly.
private var product = Product1()
func reset() {
product = Product1()
}
/// All production steps work with the same product instance.
func producePartA() {
product.add(part: "PartA1")
}
func producePartB() {
product.add(part: "PartB1")
}
func producePartC() {
product.add(part: "PartC1")
}
/// Concrete Builders are supposed to provide their own methods for
/// retrieving results. That's because various types of builders may create
/// entirely different products that don't follow the same interface.
/// Therefore, such methods cannot be declared in the base Builder interface
/// (at least in a statically typed programming language).
///
/// Usually, after returning the end result to the client, a builder
/// instance is expected to be ready to start producing another product.
/// That's why it's a usual practice to call the reset method at the end of
/// the `getProduct` method body. However, this behavior is not mandatory,
/// and you can make your builders wait for an explicit reset call from the
/// client code before disposing of the previous result.
func retrieveProduct() -> Product1 {
let result = self.product
reset()
return result
}
}
/// The Director is only responsible for executing the building steps in a
/// particular sequence. It is helpful when producing products according to a
/// specific order or configuration. Strictly speaking, the Director class is
/// optional, since the client can control builders directly.
class Director {
/// The Director works with any builder instance that the client code passes
/// to it. This way, the client code may alter the final type of the newly
/// assembled product.
func update(builder: Builder) {
self.builder = builder
}
/// The Director can construct several product variations using the same
/// building steps.
func buildMinimalViableProduct() {
builder?.producePartA()
}
func buildFullFeaturedProduct() {
builder?.producePartA()
builder?.producePartB()
builder?.producePartC()
}
}
/// It makes sense to use the Builder pattern only when your products are quite
/// complex and require extensive configuration.
///
/// Unlike in other creational patterns, different concrete builders can produce
/// unrelated products. In other words, results of various builders may not
/// always follow the same interface.
class Product1 {
func testBuilderConceptual() {
let director = Director()
Client.someClientCode(director: director)
}
}
Output.txt: Execution result
Standard basic product:
Product parts: PartA1
Custom product:
Product parts: PartA1, PartC1
enum Query {
case filter(Predicate)
case limit(Int)
/// ...
}
@discardableResult
override func limit(_ limit: Int) -> RealmQueryBuilder<Model> {
operations.append(Query.limit(limit))
return self
}
@discardableResult
override func filter(_ predicate: @escaping Predicate) ->
RealmQueryBuilder<Model> {
operations.append(Query.filter(predicate))
return self
}
enum Query {
case filter(Predicate)
case limit(Int)
case includesPropertyValues(Bool)
/// ...
}
/// Data Providers contain a logic how to fetch models. Builders accumulate
/// operations and then update providers to fetch the data.
class RealmProvider {
protocol DomainModel {
/// The protocol groups domain models to the common interface
}
func testBuilderRealWorld() {
print("Client: Start fetching data from Realm")
clientCode(builder: RealmQueryBuilder<User>())
print()