Design Patterns
Khoa CNTT – Trường Đại học Công nghệ - ĐHQGHN
Design pattern
• A design pattern is a resuable solution to a common problem in software design
• Design patterns are not specific pieces of code but rather general guidelines or
strategies that can be implemented in various programming languages and
contexts
Key characteristics
• Resuable: Can be applied to different problems in similar contexts
• Language-agnostic: Not tied to a specific programming language
• Well-documented: Includes the problem it solves, the solution, and
consequences of its use
• Tested: Proven to work through prior use and testing
Types of design patterns
• Creational patterns:
• Deal with object creation mechanisms to ensure objects are created in a way
suitable for the situation
• E.g., singleton, factory method, prototype
• Stuctural patterns:
• Focus on the composition of classes or objects to form larger structures
• E.g., Adapter, Composite, Proxy
• Behavioral patterns:
• Concerned with object interactions and responsibilities
• E.g., Observer, strategy
Benefits of design patterns
• Improved code readability and maintainability
• Encourages best practices
• Enhances flexibility
Creational patterns
Singleton pattern
Factory method pattern
Singleton pattern
Singleton pattern
• Describles the way to create an object
• Enforces one and only one object of a Singleton class
• Has the Singleton object globally accessible
Example
• Public constructor
• This constructor may instantiate an
object of this class at any time
Singleton Pattern - Example
- Private constructor
- Public method instantiates the
class object, if it is not already
instantiated
Singleton pattern
Factory Method Pattern
Factory Method Pattern
• Purpose of the factory method pattern is creating objects
• Make the software to be easily maintained and changed
Example
• You build an online store to sell knifes
• There multiple type of knifes, for example SteakKnife and ChefsKnife
→ You build a class Knife, and sub-classes SteakKnife and ChefsKnife
Example
Example
Now your sales improve, you want to add more and more types of knife
to your store.
→ New sub-classes are added.
Example
- The list of conditionals grows and grows
as new knife types are added.
→ This is getting pretty complicated
Example
Solution: We create a factory object whose role is to create objects of particular
types
• Sharpening, polishing, and packaging will stay where it is in the orderKnife method
• The responsibility of product object creation is delegated to another object
Example
- Factory object is an instance of a
Factory class which has a method to
create product objects
- The KnifeFactory object can be used
in the KnifeStore class
Example
Benefits of factory objects
• It can be used to create products for multiple clients
• If there are multiple clients that want to instantiate the same set of classes,
then by using a Factory object, you have cut out redundant code and made
the software easier to modify.
Factory method pattern
• Instead of using a separate object to create the products/objects like
Factory object, Factory method pattern uses a separate method in the
same class to create objects
Example
• Now, you want to create different specific types of knifes
- Factory object approach would subclass the factory class
Ex: BudgetKnifeFactory create budget chefs knife and budget steak knife products
QualityKnifeFactory create quality chefs knife and quality steak knife products
- Factory method approach has BugdetKnifeStore subclass KnifeStore. Also, BugdetKnifeStore
has a method (factory method) creating budget chefs knife and budget steak knife products
Example
- createKnife() is the factory
method
- Factory method is abstract
since we want the factory
method to be defined by the
subclasses
Example
Example
Factory method pattern
Factory method pattern
• The factory method design pattern defines an interface for creating
objects, but let the subclasses decide which class to instantiate
Structual patterns
Adapter
Adapter pattern
Adapter
Adapter pattern
• Software systems could have incompatible software interfaces
• Output of one system may not conform with the expected input of another system
• The adapter design pattern will help to faciliate communication between two
existing systems by providing a comptible interface
Example
- Client is your system
- Adaptee is a third-party library
- Adapter implement Target
Interface which is the interface
that the Client use
Adapter pattern
• If two interfaces are incompatible, why don’t we change one?
• We may not have direct access to the third-party library or external system.
• Our changes could break those libraries or systems
• If we change our system’s interface, the changing assumptions could break other parts of our
system (e.g., which also use those libaries)
Adapter pattern
• Implementation of an adapter design pattern:
• Design the target interface
• Implement the target interface with the adapter class
• Send the request from the client to the adapter using target interface
Example
Step 1: Design the target interface
Step 2: Implement the target interface with
the adapter class
Step 3: Send the request from the client to
the adapter using the target interface
Main program
In the main
program:
WebAdapter,
WebService, and
WebClient need
to be instantiated
Adapter
Façade pattern
Façade pattern
• Façade pattern provides a single, simplified interface for client classes
to interact with a subsystem.
• A façade is a wrapper class that encapsulates a subsystem in order to
hide the subsystem’s complexity.
Façade pattern
• Façade design pattern can be explained through a number of steps:
• Design the interface
• Implement the interface with one or more classes
• Create the façade class and wrap the classes that implement the interface
• Use the façade class to access the subsystem
Example
Without façade class, the
Customer class is
responsible for properly
creating instances of
each class Chequing,
Saving, Investment.
Example
BankService is a façade class,
Presents a simpler front to
the subsystem for the
customer client class to use.
Step 1: Design the interface
Step 2: Implement the interface with one or
more classes
Step 3: Create the façade class
Step 4: Use the façade class to access the
subsystem