Design Pattern
DESIGN PATTERN
In Object-Oriented Modeling and Design
(OOMD), design patterns are recurring solutions to common problems that arise
during the design phase of software development. Design patterns provide a set
of best practices and reusable templates that help designers and developers
create more maintainable, flexible, and efficient software systems. These
patterns have been refined over time and are based on the experiences of
software engineers in solving specific types of problems.
HISTORY:
The history of design patterns in
Object-Oriented Modeling and Design (OOMD) is closely tied to the development
of object-oriented programming (OOP) itself. Design patterns as we know them
today were popularized by the book "Design Patterns: Elements of Reusable
Object-Oriented Software," often referred to as the "Gang of
Four" (GoF) book, published in 1994.
C. Alexander (1936), computer scientist
Critical of traditional modern architecture,
patterns as solution guides in architecture, incremental building,
interaction with users, empower laypeople to create designs
Medieval cities built according to rules, not rigid masterplan.
WHY WE USE DESIGN PATTERN:
Design
patterns are used in software development for several important reasons:
1.
Reusability:
Design patterns provide proven and tested solutions to common software design
problems. By using these patterns, developers can leverage existing best
practices and avoid reinventing the wheel. This leads to more efficient
development and reduces the chances of introducing errors.
2.
Maintainability:
Design patterns promote modular and organized code. This modularization makes
it easier to understand, modify, and maintain software systems over time.
Changes to one part of the system are less likely to ripple through the entire
codebase when design patterns are used appropriately.
3.
Scalability:
Design patterns help create flexible and extensible software architectures.
This means that as requirements change or the system needs to grow, it's easier
to add new features or adapt to new circumstances without major architectural
changes. This scalability is particularly important for long-term software
projects.
4.
Communication:
Design patterns provide a common vocabulary for developers and designers. When
a team is familiar with design patterns, it's easier to discuss and communicate
design decisions. This common understanding helps with collaboration and
reduces misunderstandings.
5.
Best Practices:
Design patterns embody best practices and proven solutions to specific types of
problems. By following these patterns, developers are more likely to create
software that is efficient, maintainable, and robust. It's a way to leverage
the collective wisdom of the software development community.
TYPES OF DESIGN PATTERN:
1. Creational: These patterns are designed for class instantiation.
They can be either class-creation patterns or object-creational patterns.
2. Structural: These patterns are designed with regard to a
class's structure and composition. The main goal of most of these patterns is
to increase the functionality of the class(es) involved, without changing much
of its composition.
3. Behavioral: These patterns are designed depending on how one
class communicates with others.
CREATIONAL DESIGN PATTERN:
Each creational
pattern addresses specific needs in object creation. Creational design patterns
are a subset of design patterns that deal with object creation mechanisms. They
abstract the instantiation process, making it more flexible, efficient, and
independent of the system's architecture. There are five commonly recognized
creational design patterns:
- Singleton Pattern:
- Intent: Ensure that a class has only one instance
and provide a global point of access to that instance.
- Use Cases: Logging systems, database
connection pools, caching mechanisms.
- Factory Method Pattern:
- Intent: Define an interface for creating an object,
but let subclasses alter the type of objects that will be created.Use Cases: Frameworks for creating document
types, UI components, or when you need to defer the decision of which
class to instantiate to its subclasses.
- Abstract Factory Pattern:
- Intent: Provide an interface for
creating families of related or dependent objects without specifying
their concrete classes.
- Use Cases: GUI libraries,
cross-platform applications, or when you need to ensure that the created
objects work together seamlessly.
- Builder Pattern:
- Intent: Separate the construction of a complex
object from its representation, allowing the same construction process to
create different representations.
- Use Cases: Building complex objects
with many optional components, like HTML or XML document builders.
- Prototype Pattern:
Choosing the right pattern depends on
the requirements of your application and the level of flexibility and control
you need over object creation.
STRUCTURAL DESIGN PATTERN:
Structural design
patterns in software engineering focus on simplifying the structure of a system
by identifying relationships between objects and classes. These patterns help
to compose objects and classes into larger structures, making them more
flexible, efficient, and easier to maintain. Here are some commonly used
structural design patterns:
- Adapter Pattern:
- Intent: Allows objects with incompatible interfaces
to work together. It wraps one class with an interface into another class
that clients expect.
- Use Cases: Integrating legacy
systems, using third-party libraries, or making two incompatible classes
collaborate.
- Bridge Pattern:
- Intent: Separates an object's abstraction from its
implementation, allowing both to vary independently.
- Use Cases: Developing
platform-independent graphical interfaces, managing various database
systems, or creating different rendering engines for a shape in a drawing
application.
- Composite Pattern:
- Intent: Composes objects into tree structures to
represent part-whole hierarchies. Clients can treat individual objects
and compositions of objects uniformly.
- Use Cases: Representing hierarchical
structures like GUI components, organization structures, or file systems.
- Decorator Pattern:
- Intent: Attaches additional responsibilities to
objects dynamically. Decorators provide a flexible alternative to
subclassing for extending functionality.
- Use Cases: Adding features like
borders, scrollbars, or formatting to text in a text editor, or enhancing
the behavior of objects at runtime.
- Use Cases: Adding features like
formatting, encryption, or logging to objects without altering their core
functionality.
BEHAVIOURAL DESIGN PATTERN:
Behavioral design patterns in software
engineering deal with the interactions, responsibilities, and communication
between objects and classes. They help define how objects collaborate and
distribute responsibilities within a system. Here are some commonly used behavioral
design patterns:
1. Observer Pattern:
· Intent: Defines a
one-to-many dependency between objects so that when one object changes state,
all its dependents are notified and updated automatically.
· Use Cases: Event handling
systems, implementing publish-subscribe mechanisms, and keeping multiple views
of data in sync.
2. Strategy Pattern:
· Intent: Defines a family of
algorithms, encapsulates each one, and makes them interchangeable. Strategy
allows the algorithm to vary independently from clients using it.
· Use Cases: Implementing
different sorting algorithms, selecting various file compression methods, or
dynamically changing behavior in a game.
3. Command Pattern:
· Intent: Encapsulates a
request as an object, thereby allowing parameterization of clients with queues,
requests, and operations. It also provides support for undoable operations.
· Use Cases: Implementing
undo/redo functionality, remote control systems, or queuing requests.
4. Chain of Responsibility Pattern:
· Intent: Passes a request
along a chain of handlers. Each handler decides either to process the request
or to pass it to the next handler in the chain.
· Use Cases: Implementing
request processing pipelines, input validation, or hierarchical event handling
systems.
5. State Pattern:
· Intent: Allows an object to
alter its behavior when its internal state changes. The object will appear to
change its class.
· Use Cases: Implementing state
machines, managing the behavior of a context based on its state, or handling
complex conditional logic.
CREATIONAL
PATTERN PROGRAM:
Creational design patterns are a category of design patterns in
software engineering that deal with object creation mechanisms, trying to
create objects in a manner suitable to the situation. Here, I'll provide an
example of a common creational design pattern, the Singleton pattern, in
Python.
The Singleton pattern ensures that a class has only one instance
and provides a global point of access to that instance. Here's a simple
implementation in Python:
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super(Singleton,
cls).__new__(cls)
cls._instance.init_singleton()
return cls._instance
def init_singleton(self):
# Initialization code goes here
self.value = 0
# Example usage:
s1 = Singleton()
s1.value = 10
s2 = Singleton()
print(s1.value) # Output: 10
print(s2.value) # Output: 10 (s2 is the same instance as s1)
In this example, we create a Singleton
class with a private class variable _instance
that stores the single instance of the class. The __new__
method is overridden to ensure that only one instance is
created. When you create instances of the Singleton
class, they will all refer to the same instance.
STRUCTURAL DESIGN PATTERN PROGRAM:
Structural design patterns are another
category of design patterns that deal with how objects are composed to form
larger structures. One common structural design pattern is the
"Adapter" pattern. It allows the interface of an existing class to be
used as another interface. Here's an example of the Adapter pattern in Python:
# Adaptee (the class to be adapted)
class OldSystem:
def legacy_operation(self):
return "Legacy operation
result"
# Target interface (the interface we
want to use)
class NewSystem:
def new_operation(self):
pass
# Adapter (adapts OldSystem to
NewSystem interface)
class Adapter(NewSystem):
def __init__(self, old_system):
self._old_system = old_system
def new_operation(self):
return f"Adapted:
{self._old_system.legacy_operation()}"
# Client code
def client_code(new_system):
result = new_system.new_operation()
print(result)
# Using the Adapter to adapt the
OldSystem
old_system = OldSystem()
adapter = Adapter(old_system)
# Now, the client code can work with
the NewSystem interface via the Adapter
client_code(adapter)
In this example:
1. OldSystem represents an
existing class with a legacy operation.
2. NewSystem is the target
interface that we want to use.
3. Adapter is the adapter
class that adapts OldSystem to the NewSystem interface.
The client_code function
demonstrates how the adapter is used to invoke the legacy operation of OldSystem through the NewSystem interface.
BEHAVIOURAL DESIGN PATTERN PROGRAM:
Behavioral design patterns are design
patterns that deal with how objects interact and communicate with each other.
One commonly used behavioral design pattern is the "Observer"
pattern. The Observer pattern defines a one-to-many dependency between objects
so that when one object changes state, all its dependents (observers) are
notified and updated automatically. Here's an example of the Observer pattern
in Python:
# Subject (the object being observed)
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)
# Observer (the objects that observe
the subject)
class Observer:
def update(self, message):
pass
# ConcreteSubject (a specific subject
to be observed)
class ConcreteSubject(Subject):
def do_something(self):
# Some action that changes the state of
the subject
self.notify("Subject's state has
changed.")
# ConcreteObserver (a specific
observer that reacts to changes)
class ConcreteObserver(Observer):
def update(self, message):
print(f"Received message:
{message}")
# Client code
subject = ConcreteSubject()
observer1 = ConcreteObserver()
observer2 = ConcreteObserver()
subject.attach(observer1)
subject.attach(observer2)
subject.do_something() # Triggers notification to observers
In this example:
- Subject is the object being
observed, and it maintains a list of observers.
- Observer is an abstract
class/interface for objects that want to observe the subject.
- ConcreteSubject is a specific subject that
can change its state. It notifies its observers when its state changes.
- ConcreteObserver is a specific observer that
reacts to changes in the subject's state.
The client code demonstrates how the
Observer pattern is used. When the ConcreteSubject performs an action
that changes its state, it notifies all attached observers, and they react by
updating themselves with the new information.
-by
PRADEEP.D(21USC016)
Comments
Post a Comment