Lecture 8
Design Patterns in C#
Abdulmottaleb Elabour
1
What are Design Patterns?
• Reusable solutions for typical software design challenges are known as design
patterns. Expert object-oriented software engineers use these best practices to write
more structured, manageable, and scalable code.
• Design patterns provide a standard terminology and are specific to particular
scenarios and problems.
• Design patterns are not finished code but templates or blueprints only.
2
Key Characteristics of Design Patterns
•Reusability: Patterns can be applied to different projects and problems, saving
time and effort in solving similar issues.
•Standardization: They provide a shared language and understanding among
developers, helping in communication and collaboration.
•Efficiency: By using these popular patterns, developers can avoid finding the
solution to same recurring problems, which leads to faster development.
•Flexibility: Patterns are abstract solutions/templates that can be adapted to fit
various scenarios and requirements.
3
Types of Software Design Patterns
There are three types of Design Patterns:
•Creational Design Pattern
•Structural Design Pattern
•Behavioral Design Pattern
4
Creational Design Patterns
Creational Design Patterns focus on the process of object creation or problems
related to object creation. They help in making a system independent of how its
objects are created, composed and represented.
5
Creational Design Patterns
6
Structural Design Patterns
Structural Design Patterns solves problems related to how classes and objects are
composed/assembled to form larger structures which are efficient and flexible in
nature. Structural class patterns use inheritance to compose interfaces or
implementations.
7
Structural Design Patterns
8
Behavioral Design Patterns
Behavioral Patterns are concerned with algorithms and the assignment of
responsibilities between objects. Behavioral patterns describe not just patterns of
objects or classes but also the patterns of communication between them. These
patterns characterize complex control flow that’s difficult to follow at run-time.
9
Behavioral Design Patterns
10
Singleton Pattern
• Ensure a class has only one instance, and provide a global point of access to it.
• A particular class should have only one instance. You can use this instance
whenever you need it and therefore avoid creating unnecessary objects.
11
Singleton Pattern
This approach can work in a single-threaded environment. But
consider a multithreaded environment. In a multithreaded
environment, suppose two (or more) threads try to evaluate
this:
if (instance == null)
If they see that the instance has not been created yet, each of
them will try to create a new instance. As a result, you may end
up with multiple instances of the class.
12
Singleton Pattern optimized example for Multithreading Environment
The volatile keyword can help you to provide a serialize
access mechanism. In other words, all threads will observe
the changes by any other thread as per their execution order.
You will also remember that the volatile keyword is
applicable for class (or struct) fields; you cannot apply it to
local variables.
13
Singleton Pattern- another example
14
Singleton Pattern- another example
Trying to create instance s1.
Instantiating inside the
private constructor.
Number of instances =1
Trying to create instance s2.
Only one instance exists.
15
Why are multiple object creations a big concern?
• Object creations in the real world are treated as costly operations.
• Sometimes you may need to implement a centralized system for easy
maintenance. This also helps you to provide a global access mechanism.
16
Prototype Pattern
• Specify the kinds of objects to create using a prototypical instance, and create
new objects by copying this prototype.
• This pattern provides an alternative method for instantiating new objects by
copying or cloning an instance of an existing object. You can avoid the expense of
creating a new instance using this concept.
17
Prototype Pattern Example
Output:
Original: Ahmed, Misrata
Clone: Ahmed, Misrata
After modifying the clone:
Original: Ahmed, Misrata
Clone: Ali, Misrata
18
Prototype Pattern example with inheritance
19
What are the advantages of using the Prototype design pattern?
• You can include or discard products at runtime.
• In some contexts, you can create new instances with a cheaper cost.
• You can focus on the key activities rather than focusing on complicated instance
creation processes.
• Clients can ignore the complex creation process for objects and instead clone or
copy objects.
20
Builder Pattern
• Separate the construction of a complex object from its representation so that the
same construction processes can create different representations.
• The Builder pattern is useful for creating complex objects that have multiple
parts.
• The creation process of an object should be independent of these parts; in other
words the construction process does not care how these parts are assembled.
• You should be able to use the same construction process to create different
representations of the objects.
21
Builder Pattern
The structure of the Builder pattern
22
Builder Pattern Example – Part 1
Product – The object to be built (e.g., Vehicle)
Builder Interface
23
Builder Pattern Example – Part 2 Concrete Builders – Car
Orchestrates the building process
24
Builder Pattern Example – Part 3 Concrete Builders – Bike
Orchestrates the building process
25
What is the advantage of using a Builder pattern?
• You direct the builder to build the objects step-by-step, and you promote encapsulation
by hiding the details of the complex construction process. The director can retrieve the
final product from the builder when the whole construction is over.
• Using this pattern, the same construction process can produce different products.
What are the drawbacks associated with a Builder pattern?
• It is not suitable if you want to deal with mutable objects (which can be modified later).
• You may need to duplicate some portion of the code. These duplications may have
significant impact in some contexts.
• To create more products, you need to create more concrete builders.
26
Could you use an abstract class instead of the interface in the illustration of this
pattern?
• Yes. You could use an abstract class instead of an interface
How can you decide whether to use an abstract class or an interface in an
application?
• If you want to have some centralized or default behaviors, an abstract class is a better choice. In those cases, you can
provide some default implementation. On the other hand, the interface implementation starts from scratch and
indicates some kind of rules/contracts such as what is to be done.
Remember that if you need to add a new method in an interface, then you need to track down all the implementations of
that interface, and you need to put the concrete implementation for that method in all those places. In such a case, an
abstract class is a better choice because you can add a new method in an abstract class with a default implementation
27
Factory Method Pattern
• Define an interface for creating an object, but let subclasses decide which class to
instantiate. The Factory Method pattern lets a class defer instantiation to subclasses.
Example:
In an application, you may have different database users. For example, one user may use Oracle, and the other
may use SQL Server. Whenever you need to insert data into your database, you need to create either a
SqlConnection or an OracleConnection and only then can you proceed. If you put the code into if-else (or
switch) statements, you need to repeat a lot of code, which isn’t easily maintainable. This is because whenever
you need to support a new type of connection, you need to reopen your code and make those modifications.
28
Factory Method Pattern – Example Concrete Products – Implementations of IVehicle
Product Interface
Factory Class – Decides which object to create
29
What are the advantages of using a factory like this?
• You are separating the code that varies from the code that does not vary (in other words, the
advantages of using the Simple Factory pattern are still present). This helps you to maintain the code
easily.
• The code is not tightly coupled, so you can add new classes such as Truck, and so on, at any time in
the system without modifying the existing architecture.
30
Bridge Pattern
• Decouple an abstraction from its implementation so that the two can vary
independently.
• When changes to abstraction or implementation should not affect each other.
• When you want to combine different abstractions with different implementations.
Example:
Use a Remote to control different types of Devices (TV, PC) without tightly coupling
them.
31
Bridge Pattern – Part 1 Concrete Implementors
Implementor Interface
Concrete Implementors
32
Refined Abstraction
Bridge Pattern – Part 2
Abstraction
base(device) calls the base class constructor.
33
Bridge Pattern – Part 3
34