0% found this document useful (0 votes)
21 views43 pages

Lecture 5 - Creational Design Patterns (Builder, Prototype, Singleton)

Uploaded by

barlykov99
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views43 pages

Lecture 5 - Creational Design Patterns (Builder, Prototype, Singleton)

Uploaded by

barlykov99
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 43

Lecture 5 - Creational

Design Patterns
Builder, Prototype, Singleton
Builder

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

You might make the program too complex by creating a subclass for every possible
configuration of an object.
Problem

The constructor with lots of parameters has its downside: not all the parameters are
needed at all times.
Solution

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

Different builders execute the same task in various ways.


Solution (Director)

The director knows which building steps to execute to get a working product.
Structure
Pseudocode

The example of step-by-step construction of cars and the user guides that fit those car models.
Pseudocode
Pseudocode
Pseudocode
Pseudocode
Pseudocode
Applicability
● Use the Builder pattern to get rid of a “telescoping constructor”.

Creating such a monster is only possible in languages that support method overloading, such as C#
or Java.
Applicability
● 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).

● Use the Builder to construct Composite trees or other complex objects.


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.
2. Declare these steps in the base builder interface.
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.
4. Think about creating a director class. It may encapsulate various ways to construct a product using the
same builder object.
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
class constructor. The director uses the builder object in all further construction. There’s an alternative
approach, where the builder is passed to a specific product 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.
Pros and Cons
+ 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
● Many designs start by using Factory Method (less complicated and more
customizable via subclasses) and evolve toward Abstract Factory,
Prototype, or Builder (more flexible, but more complicated).
● Builder focuses on constructing complex objects step by step. Abstract
Factory specializes in creating families of related objects. Abstract Factory
returns the product immediately, whereas Builder lets you run some additional
construction steps before fetching the product.
● You can use Builder when creating complex Composite trees because you
can program its construction steps to work recursively.
● You can combine Builder with Bridge: the director class plays the role of the
abstraction, while different builders act as implementations.
● Abstract Factories, Builders and Prototypes can all be implemented as
Singletons.
Prototype

Also known as: Clone

Prototype is a creational design pattern that lets you copy existing objects without
making your code dependent on their classes.
Problem

Copying an object “from the outside” isn’t always possible.


Solution

Pre-built prototypes can be an alternative to subclassing.


Real-World Analogy

The division of a cell.


Structure
● Basic implementation
Structure
● Prototype registry implementation
Pseudocode

Cloning a set of objects that belong to a class hierarchy.


Pseudocode
Pseudocode
Pseudocode
Applicability
● Use the Prototype pattern when your code shouldn’t depend on the concrete
classes of objects that you need to copy.

● Use the pattern when you want to reduce the number of subclasses that only
differ in the way they initialize their respective objects.
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
won’t be able to create a separate “prototype” constructor. Thus, copying the object’s data into the newly
created clone will have to be performed within the clone method. Still, having this code in a regular constructor
is safer because the resulting object is returned fully configured 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.
4. Optionally, create a centralized prototype registry to store a catalog of frequently used prototypes. 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.
Pros and Cons
+ You can clone objects without coupling to their concrete classes.
+ You can get rid of repeated initialization code in favor of cloning pre-built
prototypes.
+ You can produce complex objects more conveniently.
+ You get an alternative to inheritance when dealing with configuration presets
for complex objects.
- Cloning complex objects that have circular references might be very tricky.
Relations with Other Patterns
● Many designs start by using Factory Method (less complicated and more customizable via
subclasses) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, but more
complicated).
● 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.
● Prototype can help when you need to save copies of Commands into history.
● Designs that make heavy use of Composite and Decorator can often benefit from using
Prototype. Applying the pattern lets you clone complex structures instead of re-constructing them
from scratch.
● Prototype isn’t based on inheritance, so it doesn’t have its drawbacks. On the other hand,
Prototype requires a complicated initialization of the cloned object. Factory Method is based on
inheritance but doesn’t require an initialization step.
● Sometimes Prototype can be a simpler alternative to Memento. This works if the object, the
state of which you want to store in the history, is fairly straightforward and doesn’t have links to
external resources, or the links are easy to re-establish.
● Abstract Factories, Builders and Prototypes can all be implemented as Singletons.
Singleton

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
● Ensure that a class has just a single instance.
● Provide a global access point to that instance.

Clients may not even realize that they’re working with the same object all the time.
Structure
Pseudocode
Pseudocode
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.

● Use the Singleton pattern when you need stricter control over global
variables.
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.
Pros and Cons
+ You can be sure that a class has only a single instance.
+ You gain a global access point to that instance.
+ The singleton object is initialized only when it’s requested for the first time.
- 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.
Relations with Other Patterns
● A Facade class can often be transformed into a Singleton since a single
facade object is sufficient in most cases.
● Flyweight would resemble Singleton if you somehow managed to reduce all
shared states of the objects to just one flyweight object. But there are two
fundamental differences between these patterns:
○ There should be only one Singleton instance, whereas a Flyweight class can have multiple
instances with different intrinsic states.
○ The Singleton object can be mutable. Flyweight objects are immutable.
● Abstract Factories, Builders and Prototypes can all be implemented as
Singletons.
Thank you!

You might also like