0% found this document useful (0 votes)
17 views23 pages

Object-Oriented Design Principles Guide

The document discusses key concepts in object-oriented analysis, design, and construction, emphasizing principles such as abstraction, modularity, encapsulation, and information hiding. It outlines the objectives of software design, including correctness, efficiency, flexibility, and maintainability, and introduces tools like Class Responsibility Collaborator (CRC) cards for organizing class responsibilities and collaborations. Additionally, it explains the importance of Abstract Data Types (ADTs) in promoting modularity and reusability in software development.

Uploaded by

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

Object-Oriented Design Principles Guide

The document discusses key concepts in object-oriented analysis, design, and construction, emphasizing principles such as abstraction, modularity, encapsulation, and information hiding. It outlines the objectives of software design, including correctness, efficiency, flexibility, and maintainability, and introduces tools like Class Responsibility Collaborator (CRC) cards for organizing class responsibilities and collaborations. Additionally, it explains the importance of Abstract Data Types (ADTs) in promoting modularity and reusability in software development.

Uploaded by

priya.a
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

UNIT-IV OBJECT ORIENTED ANALYSIS, DESIGN AND 6

CONSTRUCTION
Concepts -- the principles of abstraction, modularity, specification, encapsulation and
information hiding; concepts of abstract data type; Class Responsibility Collaborator
(CRC) model; Quality of design; Design measurements; concepts of design patterns;
Refactoring; object-oriented construction principles; object oriented metrics.

Concepts -- the principles of abstraction, modularity, specification,


encapsulation and information hiding

Software Design Concepts


Concepts are defined as a principal idea or invention that comes into our mind
or in thought to understand something. The software design concept simply
means the idea or principle behind the design. It describes how you plan to
solve the problem of designing software, and the logic, or thinking behind how
you will design software. It allows the software engineer to create the model of
the system software or product that is to be developed or built. The software
design concept provides a supporting and essential structure or model for
developing the right software.
Objectives of Software Design
1. Correctness: A good design should be correct i.e., it should correctly
implement all the functionalities of the system.
2. Efficiency: A good software design should address the resources, time, and
cost optimization issues.
3. Flexibility: A good software design should have the ability to adapt and
accommodate changes easily. It includes designing the software in a way,
that allows for modifications, enhancements, and scalability without
requiring significant rework or causing major disruptions to the existing
functionality.
4. Understand ability: A good design should be easily understandable, it
should be modular, and all the modules are arranged in layers.
5. Completeness: The design should have all the components like data
structures, modules, external interfaces, etc.
6. Maintainability: A good software design aims to create a system that is
easy to understand, modify, and maintain over time. This involves using
modular and well-structured design principles e.g.,(employing appropriate
naming conventions and providing clear documentation). Maintainability in
Software and design also enables developers to fix bugs, enhance features,
and adapt the software to changing requirements without excessive effort or
introducing new issues.

Abstraction
Abstraction is the process of focusing on important details while ignoring less
important ones. Here are some examples of abstraction in everyday life and in
computer science:
Here, there are two common abstraction mechanisms
1. Functional Abstraction
2. Data Abstraction

he system design is modular and modules support a well-defined abstraction.


Concept of abstraction is widely used in the software design. There are two
types of abstraction as shown in the following figure :

DataAbstraction :
In data abstraction, the idea is to hide the information about data and how it is
represented in the program. The analogous notion for compound data is called is
called data abstraction. Data abstraction may be a methodology that permits us
to isolate how a compound data object is employed from the small print of how
it’s constructed from the more primitive data objects. By this feature, it is
possible to create user defined data types and thus increase the power of
the programming language.
The main idea behind data abstraction is to give a clear separation between
properties of data type and the associated details. This separation is achieved so
as that the properties of the abstract data types are visible to the interface and
implementation details are hidden. Data abstraction is that the process of
refining data to its essential form. An Abstract Data Type is defined as a
knowledge type that’s defined in terms of the operations that it supports and not
in terms of its structure or implementation.
FunctionalAbstraction :
In functional abstraction, details of the algorithms to accomplish the module are
not visible to the user of the function. The users of the module need to know
only the correct calling convention. The user can call a module without
necessarily understanding how it is implemented.
Forexample :
A module to compute the log of a value can be represented by module log. The
user only need to know the interface of the module.
A specification of module specifies what a module is supposed to do.

● The main goal is to provide specifications sufficiency precise and complete


that other pieces of software can be written to interact with the piece
specified without additional information.
● The secondary goal is to include in the specification no more information
that necessary to meet the first goal.
The desirable properties that module specifications should have are following :
● Complete – The given specifications should specify the entire behavior of
the module so that only correct implementations satisfy the specifications.
The specifications must provide to the intended user all the information that
he will need to use the program correctly. The specification must provide to
the implementer, all the information about the intended use that he needs to
complete the program.
● Unambiguous – The given specifications should be unambiguous.
Specifications should have more than one interpretation.
● Understandable – The given specifications should be understandable.
Specific language should be such that specifications can be easily written.
● Implementation-independent – It is an important property of
specifications. Specifications should be given in an abstract manner
independent of the implementation of the module and should not specify any
particular method for implementation of the module. The specification
should only give the external behavior; the interior details of the module
should be decided later by the programmer.

Modularity: Modularity in software engineering means breaking complex


software systems down into smaller manageable modules or components that
are tightly coupled together. They can also be constructed as independent
subsystems. The aim, therefore, is to simplify by modularizing the program into
units or reusable building blocks that can be easily exchanged for one another.

Flexibility, scalability, maintainability, and reusability are some of the main


benefits of modular systems
Specification

In software engineering, specification is a detailed description of the


requirements and functionality of a software system. It serves as a blueprint for
both the development and testing phases of the software lifecycle.
Specifications define what the software is supposed to do and how it should
behave under various conditions

Example for specification

Functional Requirements
Functional requirements describe what the software should do. They specify
the actions or behaviors that the system must be able to perform.
Non-Functional Requirements
Non-functional requirements describe how the system should perform under
certain conditions. They cover aspects such as performance, usability,
reliability, and security.
Encapsulation
In software engineering, encapsulation is a design principle used to manage
complexity and ensure robustness by hiding the internal details of a system and
exposing only what is necessary to other parts of the system. It is widely used in
object-oriented programming (OOP) but applies more broadly in software
design

Think of a Bank Account as an example. You have money in your account, but
you can't just grab it from the bank without following certain procedures, like
using an ATM or a withdrawal slip.

Why is it important?

Encapsulation makes sure that:


1. Data is protected: People (or other parts of the program) can't just
change the data directly.
2. Data is accessed in a controlled way: The programmer decides how
others can interact with the data, through specific actions or methods.

Information Hiding

● Definition: Information hiding is the principle of hiding the internal


workings of a module and exposing only what is necessary for other parts
of the system to interact with it.

Concepts of abstract data type


In software engineering, an Abstract Data Type (ADT) is a model that
defines the behavior and properties of data structures from the user's point of
view, focusing on what the data does, rather than how it is implemented. ADTs
allow developers to think in terms of operations and behaviors without needing
to consider the underlying code or storage details.

Here are the key concepts of ADTs along with examples:

1. Abstraction
ADTs abstract away the underlying implementation details and only
expose the relevant operations. This enables users to interact with the data at a
high level.
Example:
A Stack is an ADT that allows pushing elements onto the stack and
popping them off, following a Last-In-First-Out (LIFO) principle. Whether the
stack is implemented using an array or a linked list is abstracted away.
Operations:
push(item): Adds an item to the stack.
pop(): Removes and returns the top item from the stack.
peek(): Returns the top item without removing it.

2. Encapsulation
The internal details (data and implementation) are encapsulated and
hidden from the user. The user interacts with the ADT through its well-defined
operations (or interface).
Example:
Queue is an ADT that follows a First-In-First-Out (FIFO) principle. A
queue may be implemented using a linked list or an array, but the user only sees
the operations:
enqueue(item): Adds an item to the back of the queue.
dequeue(): Removes and returns the front item from the queue.
front(): Returns the front item without removing it.

3. Operations and Behavior


ADTs define a set of operations that can be performed on the data. These
operations include creating, modifying, and querying the data, but do not dictate
how the operations are carried out.
Example:
List is an ADT that represents an ordered collection of elements. Some of
its operations include:
insert(index, item): Inserts an item at a specific position.
delete(index): Removes an item from a specific position.
get(index): Retrieves the item at the given position.
size(): Returns the number of elements in the list.

4. Modularity and Reusability


ADTs promote modularity, allowing developers to change the internal
implementation without altering the interface. This also improves code
reusability.
Example:
A Set is an ADT that stores unique elements and allows for operations like:
add(item): Adds an item to the set.
remove(item): Removes an item from the set.
contains(item): Checks if an item is present in the set.
Whether the set is implemented using a hash table or a balanced tree doesn't
matter to the user as long as these operations behave as expected.

5. Data Hiding
The actual structure and data representation are hidden from the user. The
user is only concerned with the interface and its correctness, not with how data
is managed internally.
Example:
A Dictionary (Map) ADT stores key-value pairs. Some of its operations are:
put(key, value): Adds a key-value pair to the dictionary.
get(key): Retrieves the value associated with the key.
remove(key): Removes a key-value pair.
Whether this is implemented using a hash table, binary search tree, or another
structure is hidden.

Type of ADTs

ADTs are often categorized based on their usage and behavior. Below are
examples of common ADTs:
1. Stack:
A collection of elements with LIFO behavior.
Operations: push, pop, peek.
Example: A stack is used in expression evaluation or function call stacks in
programming languages.
2. Queue:
A collection of elements with FIFO behavior.
Operations: enqueue, dequeue, front.
Example: Queues are used in scheduling algorithms or buffering in computer
systems.
3. List:
An ordered collection of elements.
Operations: insert, delete, get, size.
Example: Lists are used to store ordered data like a playlist of songs.

Benefits of ADTs:
1. Simplifies Problem Solving: By abstracting implementation details,
developers can focus on solving higher-level problems.
2. Promotes Modularity: ADTs separate the interface from the implementation,
allowing for independent development and testing.
3, Enhances Code Reusability: Once an ADT is defined, it can be reused in
different applications without modification.
4. Improves Maintainability: Changes in internal implementation do not affect
the code that uses the ADT.
By using ADTs, software engineers can build complex systems with a clear and
structured approach, ensuring that the core logic remains abstracted from the
implementation details.

Class-Responsibility-Collaboration
A Class-Responsibility-Collaboration (CRC) card is a structured tool used in
object-oriented software design. It captures essential information about a class,
including its name, responsibilities, and collaborations with other classes. CRC
cards facilitate collaborative discussions among team members and help in
refining the design of software systems. Overall, they serve as valuable aids in
the iterative process of designing and refining software solutions.

CRC (Class, Responsibility, Collaboration) cards are a design tool used in


object-oriented programming to capture and organize information about classes,
their responsibilities, and their collaborations within a software system.
Purpose of CRC cards in software design
The purpose of CRC cards in software design include:
● Clarify Class Responsibilities: CRC cards help identify and define the
responsibilities of each class in the system. By listing the responsibilities of a
class on a card, developers can gain a clear understanding of what each class
is supposed to do.
● Identify Collaborations: CRC cards also specify the collaborations between
classes. This includes identifying which classes need to interact with each
other to fulfill their responsibilities. By outlining these collaborations,
developers can ensure that the interactions between classes are well-defined
and appropriate.
● Encourage Communication and Collaboration: CRC cards are typically
used in group settings, such as brainstorming sessions or design meetings.
They encourage team members to actively participate in discussions about
the system’s design, fostering collaboration and communication among team
members.
● Iterative Design and Refinement: CRC cards support an iterative approach
to software design. As the design evolves and requirements change, CRC
cards can be easily updated or revised to reflect these changes. This allows
for continuous refinement of the system’s design throughout the
development process.
Components of CRC Cards
CRC (Class-Responsibility-Collaboration) cards consist of three main
components:
● Class: The class represents a software entity or component in the system. It
encapsulates data (attributes or properties) and behavior (methods or
functions) related to a specific concept or functionality. On a CRC card, the
class name is typically written at the top.
● Responsibility: Responsibility refers to the tasks or functions that a class is
responsible for performing. It defines what the class does or what it is
expected to accomplish within the system. Responsibilities are listed on the
card below the class name, often as bullet points or short phrases.
● Collaboration: Collaboration describes the interactions or relationships that
a class has with other classes in the system. It specifies how the class
communicates or cooperates with other classes to fulfill its responsibilities.
Collaborations are listed on the card alongside the responsibilities, indicating
the classes with which the current class interacts.

These components work together to provide a concise and structured


representation of the class’s role, behavior, and relationships within the system.
By organizing this information on index cards, developers can visually analyze
and discuss the design of the system, identify potential design flaws, and
iteratively refine the system’s architecture.
Benefits of Using CRC Cards
Using CRC (Class-Responsibility-Collaboration) cards in software design offers
several benefits:
● Visualization: CRC cards provide a tangible and visual representation of the
system’s design. This helps developers conceptualize the structure, behavior,
and relationships between classes in the system more easily.
● Collaboration: CRC cards facilitate collaborative discussions among team
members during design meetings or brainstorming sessions. They encourage
active participation and help ensure that everyone’s ideas and perspectives
are considered.
● Clarity and Understanding: By breaking down the responsibilities and
collaborations of each class into concise bullet points, CRC cards help
clarify the purpose and role of each class in the system. This enhances
understanding and ensures that all team members have a clear view of the
system’s design.
● Iterative Design: CRC cards support an iterative approach to software
design. As the design evolves and requirements change, CRC cards can be
easily updated or revised to reflect these changes. This allows for continuous
refinement of the system’s architecture throughout the development process.
● Rapid Prototyping: CRC cards enable rapid prototyping and exploration of
design alternatives. Teams can quickly create, modify, and rearrange CRC
cards to experiment with different class hierarchies, responsibilities, and
collaborations.
How to Create CRC Cards?
Creating CRC (Class-Responsibility-Collaboration) cards involves several
steps:
● Step 1: Identify Classes:
o Start by identifying the classes or objects in your system. Classes
represent the key entities or components in the software that
encapsulate data and behavior related to specific concepts or
functionalities.
● Step 2: List Responsibilities:
o For each class, list down the responsibilities or tasks that it is
responsible for performing. Responsibilities should describe what
the class does or what it is expected to accomplish within the
system. Be concise and specific when defining responsibilities.
● Step 3: Define Collaborations:
o Determine how each class collaborates or interacts with other
classes in the system. Specify the dependencies, relationships, or
communications between classes to fulfill their responsibilities.
Identify which classes send messages to or receive messages from
the current class.
● Step 4: Create Cards:
o Once you have identified the classes, responsibilities, and
collaborations, create CRC cards for each class. You can use
physical index cards or digital tools to create the cards. Write the
class name at the top of each card and list the responsibilities and
collaborations below.
● Step 5: Organize Cards:
o Arrange the CRC cards on a table or board where they are visible
to all team members. Organize the cards in a way that makes sense
for the system’s architecture, such as grouping related classes
together or arranging them hierarchically.
Example of CRC cards
Let’s understand CRC Cards using example of banking system.
1. Class: Account
Responsibilities:
● Store account holder information (name, address, contact details).

● Maintain account balance.

● Perform transactions (deposit, withdrawal).

● Generate account statements.


Collaborations:
● Collaborates with Transaction class for performing deposit and withdrawal
operations.
● Collaborates with Statement class to generate account statements.
2. Class: Transaction
Responsibilities:
● Record transaction details (date, type, amount).

● Update account balance based on deposit or withdrawal operations.


Collaborations:
● Collaborates with Account class to perform deposit and withdrawal
operations.
3. Class: Statement
Responsibilities:
● Generate account statements for a specified period.

● Include transaction details (date, type, amount) in the statement.


Collaborations:
● Collaborates with Account class to access transaction data for generating
statements.
In this example:
● The Account class represents bank accounts and is responsible for storing
account holder information, maintaining balances, performing transactions,
and generating statements.
● The Transaction class handles individual transactions and records
transaction details such as date, type, and amount. It collaborates with the
Account class to update account balances.
● The Statement class is responsible for generating account statements for a
specified period. It collaborates with the Account class to access transaction
data for generating statements.
These CRC cards provide a structured overview of the responsibilities and
collaborations of each class in the banking system, helping to clarify the
system’s design and functionality.
Guidelines and Best Practices for CRC Cards
When using CRC (Class-Responsibility-Collaboration) cards, it’s essential to
follow guidelines and best practices to ensure their effectiveness in software
design. Here are some guidelines and best practices for using CRC cards:
● Keep it Simple and Concise: Write clear and concise descriptions of class
responsibilities and collaborations. Avoid including unnecessary details or
technical jargon that may confuse team members.
● Focus on Responsibilities: Emphasize the responsibilities of each class
rather than implementation details. This helps maintain a clear separation of
concerns and ensures that each class has a single, well-defined purpose.
● Use Active Collaboration: Encourage active participation and collaboration
among team members during CRC card sessions. Invite input from all team
members and consider different perspectives when defining class
responsibilities and collaborations.
● Iterate and Refine: Treat CRC cards as living documents that evolve
throughout the design process. Continuously review and refine the cards as
the system design progresses, incorporating feedback and insights gained
from further analysis or discussions.
● Validate Requirements: Ensure that the responsibilities and collaborations
listed on CRC cards accurately reflect the system’s requirements and design
goals. Validate each class’s responsibilities against the system’s use cases,
user stories, or functional requirements.
● Keep Cards Organized: Organize CRC cards in a way that makes them
easy to read and understand. Group related classes together, arrange them
hierarchically if necessary, and use visual cues such as colors or borders to
highlight important information.
5.5 Design Measurements

To see how these measurements reveal information about the design, design
measurements can be based on three different characteristics:

(i) Relationships between classes (e.g., friendship, inheritance),

(ii) Types of interactions between classes (e.g., class–attribute interaction,


class– method interaction, method–method interaction), and

(iii) Due to design changes (i.e., whether a change flows toward or away from a
class). For each class in a design, they defined metrics that count the
interactions between the class and other classes or methods. Then, using
empirical information about the design for a real system and the resulting
system’s faults and failures, they analyzed the relationship between the type of
coupling and the kinds of faults that were found.

Quality of Design

Adopt design principles to ensure highest quality of the code design

Quality of design in software engineering is focused on the code structure.


There are many ways to implement the desired behaviour of a software product.
Careless implementation of desired behaviour delivers poor quality of design.
Consequently, the quality of the delivery gets compromised.

It is therefore paramount to invest time and effort to ensure that quality of the
designed code structure is optimal. There are two branches of industry standards
that serve as guidelines when it comes to producing optimal quality of the
designed code structure:

1. Design principles
2. Design patterns
Design patterns have been introduced more than 25 years ago (Design Patterns:
Elements of Reusable Object-Oriented Software, published in 1994). Most
software engineers are by now familiar with many design patterns, which is a
great improvement compared to earlier days of software engineering practices.

Design principles, on the other hand, are still not as widely accepted as design
patterns are. Now may be a good time to pay a bit closer attention to what
design principles mean and how to adopt them in our daily practice.

What are design principles?


Organizing structural components of a software system should be following
accepted industry standards. These standards comprise the body of design
principles.

The standardized body of design principles has two levels of abstraction:

1. Coarse-grained design principles


2. Fine-grained design principles
Coarse-grained design principles are difficult to apply in daily practice because
they are quite abstract. There are four coarse-grained design principles:

1. Low coupling
2. High cohesion
3. Low complexity
4. Proper encapsulation
Fine-grained design principles are less abstract and therefore easier to apply in
daily practice. Adhering to fine-grained design principles ensures adherence to
more abstract, coarse-grained design principles.

What are the benefits of design principles?

Design principles are helpful in building common basis of architectural


knowledge. By following guidelines on how to implement fine-grained design
principles, software engineers get enabled to build, understand, and maintain
high-quality software systems. Systems built following design principles can
successfully grow into large scale systems. Following those principles is also
helpful in preventing us from unforeseen pitfalls.

Design Patterns

In Object-Oriented Analysis and Design (OOAD), a design pattern is a


reusable, general solution to a commonly occurring problem in software design.
It provides a template or blueprint that can be applied in different contexts to
solve problems related to object creation, interaction, or composition.

Design patterns in OOAD help guide the design process by offering best
practices, ensuring systems are scalable, maintainable, and flexible. Instead of
reinventing the wheel for every design problem, developers can apply patterns
that have already proven effective.

Key Characteristics of Design Patterns

1. Reusable: Patterns provide tried-and-tested solutions that can be used


across different projects.
2. General: They are not tied to a specific application but can be adapted to
different situations.
3. Flexible: Design patterns promote flexibility by decoupling parts of the
system, enabling changes without widespread impact.

Benefits of Design Patterns in OOAD

● Improved Communication: Design patterns provide a shared


vocabulary among developers, making it easier to communicate complex
ideas.
● Efficient Problem-Solving: Patterns save time by providing proven
solutions to recurring problems.
● Better Design: They promote principles like encapsulation, modularity,
and low coupling, leading to cleaner and more maintainable systems.
● Extensibility: Patterns enable systems to be more adaptable to future
changes.

Categories of Design Patterns in OOAD

1. Creational Patterns

2. Structural Pattern

3. Behavioral Patterns

Applying GoF design patterns

Applying GoF (Gang of Four) design patterns refers to using a set of


foundational, time-tested solutions to common software design problems, as
outlined in the book "Design Patterns: Elements of Reusable Object-Oriented
Software" by the Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson,
and John Vlissides). These patterns provide a shared language for developers
and offer a blueprint for building flexible, scalable, and maintainable object-
oriented systems.

Categories of GoF Design Patterns

GoF patterns are divided into three main categories:

1. Creational Patterns: Deal with object creation mechanisms, trying to


create objects in a manner suitable for the situation.
2. Structural Patterns: Concerned with object composition, or how objects
can be combined to form larger structures.
3. Behavioral Patterns: Focus on communication between objects,
defining how they interact and distribute responsibility.

Creational Patterns

These patterns abstract the instantiation process and make it easier to decouple
code from specific object types.

1. Singleton: Ensures a class has only one instance and provides a global
point of access to it.
o Example: A Configuration class that loads settings only once and is
accessible throughout the application.
2. Factory Method: Defines an interface for creating an object but allows
subclasses to alter the type of objects that will be created.
o Example: A ShapeFactory that returns different Shape objects (e.g.,
Circle, Rectangle) based on input.
3. Abstract Factory: Provides an interface to create families of related or
dependent objects without specifying their concrete classes.
o Example: A UIFactory that can create WindowsButton and
WindowsCheckbox for Windows, or MacButton and
MacCheckbox for macOS.
4. Builder: Separates the construction of a complex object from its
representation, allowing the same construction process to create different
representations.
o Example: A MealBuilder that can create different types of meals
(e.g., vegan, non-vegan) using the same building steps.
5. Prototype: Creates new objects by copying an existing object, known as
the prototype.
o Example: An object pool that clones existing objects to avoid the
cost of creating new ones.

Structural Patterns

These patterns define how classes and objects can be combined to form larger
structures while keeping the system flexible and efficient.

1. Adapter: Allows incompatible interfaces to work together by acting as a


bridge between them.
o Example: An AudioPlayer class that can play different audio
formats using different adapters (e.g., Mp3Adapter, Mp4Adapter).
2. Decorator: Adds responsibilities to an object dynamically without
altering its structure.
o Example: A Coffee class that can be extended with decorators like
MilkDecorator and SugarDecorator to enhance the object at
runtime.
3. Facade: Provides a simplified interface to a complex subsystem, making
the subsystem easier to use.
o Example: A HomeTheaterFacade that simplifies interactions with
components like TV, SoundSystem, and DVDPlayer.
4. Proxy: Provides a placeholder or surrogate for another object to control
access, reduce complexity, or add functionality.
o Example: A RemoteProxy that controls access to a RealServer
object, handling network calls and communication.
5. Composite: Composes objects into tree structures to represent part-whole
hierarchies. A group of objects is treated the same as a single instance of
an object.
o Example: A FileSystem where both File and Folder objects can be
treated uniformly.
6. Bridge: Separates an object’s abstraction from its implementation,
allowing them to evolve independently.
o Example: A RemoteControl interface that controls both TV and
Radio devices, while keeping their implementation separate.
7. Flyweight: Reduces memory usage by sharing common parts of state
between multiple objects instead of creating new instances.
o Example: A Character object in a text editor where only one
instance of each letter is created and shared.

Behavioral Patterns

These patterns are concerned with communication between objects, focusing on


how objects interact and how responsibilities are divided.

1. Observer: Defines a one-to-many dependency between objects so that


when one object changes state, all its dependents are notified and updated
automatically.
o Example: A WeatherStation that notifies multiple Display objects
when the temperature changes.
2. Strategy: Defines a family of algorithms, encapsulates each one, and
makes them interchangeable at runtime.
o Example: A Payment class that uses different payment strategies
(CreditCard, PayPal) to process transactions.
3. Command: Encapsulates a request as an object, allowing
parameterization of clients with queues, requests, and operations.
o Example: A RemoteControl that uses command objects to execute
different actions like TurnOnTV or IncreaseVolume.
4. State: Allows an object to change its behavior when its internal state
changes, appearing as if the object has changed its class.
o Example: A TrafficLight class that behaves differently in its Green,
Yellow, or Red states.
5. Chain of Responsibility: Passes a request along a chain of potential
handlers, where each handler can either process the request or pass it on.
o Example: A support system where a request can pass through
multiple layers (Level1Support, Level2Support) until it’s resolved.
6. Mediator: Centralizes communication between objects by encapsulating
how a set of objects interact.
o Example: A ChatRoom that acts as a mediator between chat
participants, controlling message delivery.
7. Iterator: Provides a way to access elements of a collection sequentially
without exposing its underlying structure.
o Example: A ListIterator that allows traversing elements of a List
without knowing its implementation details.
8. Template Method: Defines the skeleton of an algorithm, allowing
subclasses to redefine specific steps without changing the overall
structure.
o Example: A Game class where specific game logic like start, play,
and end are defined by subclasses (e.g., ChessGame,
FootballGame).
9. Visitor: Separates an algorithm from the object structure it operates on by
allowing new operations to be added without modifying the objects
themselves.
o Example: A TaxCalculator that visits different Product objects to
apply the appropriate tax.

10. Interpreter explains how to express a languages grammar and offers


an interpreter to deal with it.

[Link] : When we want to store an objects state for subsequent


restoration, we utilize the memento design pattern.

Applying GoF Patterns

● Identifying Problems: Recognize recurring design problems in your


system, such as object creation, behavior delegation, or structural
complexities.
● Selecting the Right Pattern: Choose a GoF pattern that fits the context
of the problem and provides the best trade-off between flexibility and
complexity.
● Implementing: Implement the pattern by following its defined structure
(e.g., using interfaces, abstract classes, or composition).
● Refactoring: Sometimes, applying a GoF pattern requires refactoring
existing code to introduce more flexibility, decoupling, or modularity.

Benefits of Applying GoF Patterns

1. Reusability: Patterns provide reusable solutions that can be applied to


different problems.
2. Maintainability: Patterns help create systems that are easier to extend,
refactor, and maintain.
3. Flexibility: Many GoF patterns support polymorphism and composition,
allowing systems to evolve without breaking existing code.
4. Common Language: Patterns serve as a common vocabulary among
developers, making communication more efficient.

Incorporating GoF design patterns into your design process can significantly
enhance the quality of software architecture by promoting best practices and
reducing common pitfalls.

What is refactoring?
Refactoring is the process of restructuring code, while not changing its original
functionality. The goal of refactoring is to improve internal code by making
many small changes without altering the code's external behaviour. Computer
programmers and software developers refactor code to improve the design,
structure and implementation of software. The refactoring process features
many small changes to a program's source code..

What is the purpose of refactoring?


Refactoring improves code by making it:

● More efficient by addressing dependencies and complexities.

● More maintainable or reusable by increasing efficiency and readability.

● Cleaner so it is easier to read and understand.

● Easier for software developers to find and fix bugs or vulnerabilities in the
code.
This image shows the process of making several small code refactorings.
When should code be refactored?
Refactoring can be performed after a product has been deployed, before adding
updates and new features to existing code, or as a part of day-to-day
programming.

A better time to perform refactoring, though, is before adding updates or new


features to existing code. When performed at this point, refactoring makes it
easier for developers to build onto the existing code because they are going
back and simplifying the code, making it easier to read and understand.

What are the benefits of refactoring?


Refactoring can provide the following benefits:

● Makes the code easier to understand and read because the goal is to simplify
code and reduce complexities.
● Improves maintainability and makes it easier to spot bugs or make further
changes.
● Encourages a more in-depth understanding of code. Developers have to
think further about how their code will mix with code already in the code
base.
● Focus remains only on functionality. Not changing the code's original
functionality ensures the original project does not lose scope.
What are the challenges of refactoring?
Challenges do come with the process, however. Some of these include:

● The process will take extra time if a development team is in a rush and
refactoring is not planned for.
● Without clear objectives, refactoring can lead to delays and extra work.

● Refactoring cannot address software flaws by itself, as it is made to clean


code and make it less complex.
object-oriented construction principles

 Abstraction: Focuses on representing essential features, hiding unnecessary


details.
 Encapsulation: Bundles data and methods together, restricting access to
object internals.
 Inheritance: Allows new classes to inherit properties from existing ones,
enabling reuse.
 Polymorphism: Enables a single interface to represent different underlying
forms, enhancing flexibility.
 Modularity: Decomposes a system into smaller parts, each with a specific
responsibility.
 Low Coupling & High Cohesion: Ensures minimal dependencies between
modules and that each module serves a focused purpose.

bject-Oriented Design

In the object-oriented design method, the system is viewed as a collection of


objects (i.e., entities). The state is distributed among the objects, and each object
handles its state data. For example, in a Library Automation Software, each
library representative may be a separate object with its data and functions to
operate on these data. The tasks defined for one purpose cannot refer or change
data of other objects. Objects have their internal data which represent their state.
Similar objects create a class. In other words, each object is a member of some
class. Classes may inherit features from the superclass.

The different terms related to object design are:


1. Objects: All entities involved in the solution design are known as
objects. For example, person, banks, company, and users are considered
as objects. Every entity has some attributes associated with it and has
some methods to perform on the attributes.
2. Classes: A class is a generalized description of an object. An object is an
instance of a class. A class defines all the attributes, which an object can
have and methods, which represents the functionality of the object.
3. Messages: Objects communicate by message passing. Messages consist
of the integrity of the target object, the name of the requested operation,
and any other action needed to perform the function. Messages are often
implemented as procedure or function calls.
4. Abstraction In object-oriented design, complexity is handled using
abstraction. Abstraction is the removal of the irrelevant and the
amplification of the essentials.
5. Encapsulation: Encapsulation is also called an information hiding
concept. The data and operations are linked to a single unit.
Encapsulation not only bundles essential information of an object
together but also restricts access to the data and methods from the outside
world.
6. Inheritance: OOD allows similar classes to stack up in a hierarchical
manner where the lower or sub-classes can import, implement, and re-use
allowed variables and functions from their immediate [Link]
property of OOD is called an inheritance. This makes it easier to define a
specific class and to create generalized classes from specific ones.
7. Polymorphism: OOD languages provide a mechanism where methods
performing similar tasks but vary in arguments, can be assigned the same
name. This is known as polymorphism, which allows a single interface is
performing functions for different types. Depending upon how the service
is invoked, the respective portion of the code gets executed.

You might also like