Unit 3designpattern
Unit 3designpattern
One structural design pattern that enables the usage of an existing class’s
interface as an additional interface is the adapter design pattern. To make
two incompatible interfaces function together, it serves as a bridge. This
pattern involves a single class, the adapter, responsible for joining
functionalities of independent or incompatible interfaces.
What is Adapter Design Pattern?
Two incompatible interfaces or systems can cooperate by using the adapter
design pattern, a structural design pattern. Because of incompatible
interfaces, it serves as a bridge between two classes that would not
otherwise be able to communicate. The adapter approach is very helpful
when attempting to incorporate third-party libraries or legacy code into a new
system.
Real-World Example of Adapter Design Pattern
Let’s understand this concept using a simple example:
Suppose you have two buddies, one of them speaks French exclusively and
the other English exclusively. The language barrier prevents them from
communicating the way you want them to.
You act as an adapter, translating messages between them. Your role
allows the English speaker to convey messages to you, and you convert
those messages into French for the other person.
In this way, despite the language difference, your adaptation enables
smooth communication between your friends.
This role you play is similar to the Adapter design pattern, bridging the
gap between incompatible interfaces.
Components of Adapter Design Pattern
Below are the components of adapter design pattern:
Target Interface: Defines the interface expected by the client. It
represents the set of operations that the client code can use. It’s the
common interface that the client code interacts with.
Adaptee: The existing class or system with an incompatible interface that
needs to be integrated into the new system. It’s the class or system that
the client code cannot directly use due to interface mismatches.
Adapter: A class that implements the target interface and internally uses
an instance of the adaptee to make it compatible with the target interface.
It acts as a bridge, adapting the interface of the adaptee to match the
target interface.
Client: The code that uses the target interface to interact with objects. It
remains unaware of the specific implementation details of the adaptee
and the adapter. It’s the code that benefits from the integration of the
adaptee into the system through the adapter.
Different implementations of Adapter Design Pattern
The Adapter Design Pattern can be applied in various ways depending on
the programming language and the specific context. Here are the primary
implementations:
1. Class Adapter (Inheritance-based)
In this approach, the adapter class inherits from both the target
interface (the one the client expects) and the adaptee (the existing
class needing adaptation).
Programming languages that allow multiple inheritance, like C++, are
more likely to use this technique.
However, in languages like Java and C#, which do not support multiple
inheritance, this approach is less frequently used.
2. Object Adapter (Composition-based)
The object adapter employs composition instead of inheritance. In this
implementation, the adapter holds an instance of the adaptee and
implements the target interface.
This approach is more flexible as it allows a single adapter to work with
multiple adaptees and does not require the complexities of inheritance.
The object adapter is widely used in languages like Java and C#.
3. Two-way Adapter
A two-way adapter can function as both a target and an adaptee,
depending on which interface is being invoked.
This type of adapter is particularly useful when two systems need to
work together and require mutual adaptation.
4. Interface Adapter (Default Adapter)
When only a few methods from an interface are necessary, an
interface adapter can be employed.
This is especially useful in cases where the interface contains many
methods, and the adapter provides default implementations for those
that are not needed.
This approach is often seen in languages like Java, where abstract
classes or default method implementations in interfaces simplify the
implementation process.
How Adapter Design Pattern works?
Below is how adapter design pattern works:
Step 1: The client initiates a request by calling a method on the adapter
via the target interface.
Step 2: The adapter maps or transforms the client’s request into a format
that the adaptee can understand using the adaptee’s interface.
Step 3: The adaptee does the actual job based on the translated request
from the adapter.
Step 4: The client receives the results of the call, remaining unaware of
the adapter’s presence or the specific details of the adaptee.
The Strategy Design Pattern defines a family of algorithms, encapsulates each one,
and makes them interchangeable, allowing clients to switch algorithms dynamically
without altering the code structure.
What is the Strategy Design Pattern?
The Strategy Design Pattern is a behavioral design pattern that allows you to
define a family of algorithms or behaviors, put each of them in a separate
class, and make them interchangeable at runtime. This pattern is useful
when you want to dynamically change the behavior of a class without
modifying its code.
Characteristics of this design pattern
This pattern exhibits several key characteristics, such as:
Defines a family of algorithms: The pattern allows you to encapsulate
multiple algorithms or behaviors into separate classes, known as
strategies.
Encapsulates behaviors: Each strategy encapsulates a specific
behavior or algorithm, providing a clean and modular way to manage
different variations or implementations.
Enables dynamic behavior switching: The pattern enables clients to
switch between different strategies at runtime, allowing for flexible and
dynamic behavior changes.
Promotes object collaboration: The pattern encourages collaboration
between a context object and strategy objects, where the context
delegates the execution of a behavior to a strategy object.
Components of the Strategy Design Pattern
1. Context
A class or object known as the Context assigns the task to a strategy object
and contains a reference to it.
It serves as an intermediary between the client and the strategy, offering
an integrated approach for task execution without exposing every detail of
the process.
The Context maintains a reference to a strategy object and calls its
methods to perform the task, allowing for interchangeable strategies to be
used.
2. Strategy Interface
An abstract class or interface known as the Strategy Interface specifies a set
of methods that all concrete strategies must implement.
As a kind of agreement, it guarantees that all strategies follow the same
set of rules and are interchangeable by the Context.
The Strategy Interface promotes flexibility and modularity in the design by
establishing a common interface that enables decoupling between the
Context and the specific strategies.
3. Concrete Strategies
Concrete Strategies are the various implementations of the Strategy
Interface. Each concrete strategy provides a specific algorithm or behavior
for performing the task defined by the Strategy Interface.
Concrete strategies encapsulate the details of their respective algorithms
and provide a method for executing the task.
They are interchangeable and can be selected and configured by the
client based on the requirements of the task.
4. Client
The Client is responsible for selecting and configuring the appropriate
strategy and providing it to the Context.
It knows the requirements of the task and decides which strategy to use
based on those requirements.
The client creates an instance of the desired concrete strategy and
passes it to the Context, enabling the Context to use the selected strategy
to perform the task.
Communication between the Components
In the Strategy Design Pattern, communication between the components
occurs in a structured and decoupled manner. Here’s how the components
interact with each other:
Client to Context:
o The Client, which knows the requirements of the task, interacts
with the Context to initiate the task execution.
o The Client selects an appropriate strategy based on the task
requirements and provides it to the Context.
o The Client may configure the selected strategy before passing it
to the Context if necessary.
Context to Strategy:
o The Context holds a reference to the selected strategy and
delegates the task to it.
o The Context invokes a method on the strategy object, triggering
the execution of the specific algorithm or behavior encapsulated
within the strategy.
Strategy to Context:
o Once the strategy completes its execution, it may return a result
or perform any necessary actions.
o The strategy communicates the result or any relevant information
back to the Context, which may further process or utilize the
result as needed.
Strategy Interface as Contract:
o The Strategy Interface serves as a contract that defines a set of
methods that all concrete strategies must implement.
o The Context communicates with strategies through the common
interface, promoting interchangeability and decoupling.
Decoupled Communication:
o Since the components’ communication is decoupled, the Context
is not required to be aware of the exact details of how each
strategy carries out the task.
o As long as they follow the same interface, strategies can be
switched or replaced without affecting the client or other
strategies.
Real-World Analogy of Strategy Design Pattern
Imagine you’re planning a trip to a new city, and you have several options for
getting there: by car, by train, or by plane. Each mode of transportation
offers its own set of advantages and disadvantages, depending on factors
such as cost, travel time, and convenience.
Problem Statement:
Let’s consider a hotel. This hotel has a hotel keeper. There are a lot of
restaurants inside the hotel e.g. Veg restaurants, Non-Veg restaurants, and
Veg/Non Both restaurants. You, as a client want access to different menus of
different restaurants.
You do not know what are the different menus they have. You just have
access to a hotel keeper who knows his hotel well.
Whichever menu you want, you tell the hotel keeper and he takes it out of
the respective restaurants and hands it over to you.
The Gang of Four (GOF) patterns are set of 23 common software design
patterns introduced in the book Design Patterns: Elements of Reusable
Object-Oriented Software.