Chapter 22 - Design Patterns and clean code principles Flashcards

1
Q

Difference between design principles and patterns

A

design principles guide the overall structure and organization of your code, promoting qualities like maintainability and scalability, while design patterns offer specific solutions to recurring design problems in alignment with these principles. Principles are more abstract and foundational, while patterns are more concrete and implementation-focused. However, both are essential for writing clean, maintainable, and scalable code in Java (or any programming language).

Design Principles:
Design principles are general guidelines or rules that help in designing software that is maintainable, scalable, and understandable. They are high-level concepts that guide the overall structure and organization of your code.
Examples of design principles include SOLID principles (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion), DRY (Don’t Repeat Yourself), KISS (Keep It Simple, Stupid), and others.
These principles are more about the mindset and approach to software design rather than specific implementations.

Design Patterns:
Design patterns are specific solutions to common problems encountered during software development. They are tried and tested solutions to recurring design problems.
Design patterns provide concrete implementations to achieve goals aligned with design principles.
Examples of design patterns include Singleton, Factory Method, Observer, Strategy, Adapter, and many others.
Each design pattern has its specific context, structure, and participants.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Encapsulate What Varies Design principle

A

Identify the aspects of your application that vary and separate them from what stays the same

Encapsulating what varies means identifying the aspects of your codebase that are likely to change in the future and encapsulating them behind a stable interface. By doing this, you reduce the ripple effect of changes. When a change is needed, you only need to modify the encapsulated part, without impacting the rest of the codebase. This promotes maintainability, as it minimizes the risk of unintended side effects when making changes.

example from the spring boot when we have UserService interface and can have different implementations for example with MongoDB or JPA.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Program to an Interface, not an
Implementation

A

“Program to an Interface, not an Implementation” is a design principle that emphasizes the importance of using interfaces (or abstract classes) to define the behavior of components in your code rather than relying on concrete implementations. This principle promotes flexibility, extensibility, and maintainability in software design.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Favor Composition Over
Inheritance

A

“Favor Composition Over Inheritance” is a design principle that suggests preferring composition (has-a relationship) over inheritance (is-a relationship) when designing the structure of classes and their relationships. This principle encourages building systems by composing smaller, more cohesive components rather than relying heavily on inheritance hierarchies.

When favoring composition over inheritance, it’s preferable to use interface implementation (implements) rather than class inheritance (extends) to achieve the desired functionality.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

SOLID

A

Single Responsibility Principle (SRP)
Open/Closed Principle (OCP)
Liskov Substitution Principle (LSP)
Interface Segregation Principle (ISP)
Dependency Inversion Principle (DIP)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Single Responsibility Principle (SRP)

A

The Single Responsibility Principle states that a class should have only one reason to change, meaning that it should have only one responsibility or job. In other words, a class should be responsible for only one aspect of the functionality within a system.

Consider a class Employee that is responsible for storing employee information and also for formatting employee data for display. This violates SRP, as the class has two reasons to change: if the employee information structure changes or if the formatting requirements change.

Emagine spring boot, UserService class is responsible for both user management (e.g., saving users to the database) and sending welcome emails. This violates the Single Responsibility Principle because the class has multiple reasons to change: if the user management logic changes or if the email sending logic changes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Open/Closed Principle (OCP)

A

The Open/Closed Principle (OCP) is one of the five SOLID principles of object-oriented design. It states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. In simpler terms, this means that once a class is written and tested, it should not be modified to add new functionality; instead, it should be extended through inheritance or composition.

OrderService class is directly responsible for calculating the total cost of an order and applying a discount for premium customers. If a new type of customer or a different discount strategy is introduced, the OrderService class needs to be modified, violating the Open/Closed Principle.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Liskov Substitution Principle (LSP)

A

It states that objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. In simpler terms, this means that subclasses should be substitutable for their base classes without altering the desired behavior of the program.

Imagine you have a class called Animal that represents all animals. Now, let’s say you have a subclass called Dog that represents dogs, and another subclass called Cat that represents cats.

According to the Liskov Substitution Principle (LSP):

You should be able to use a Dog object wherever you would use an Animal object, without anything going wrong.
Similarly, you should be able to use a Cat object wherever you would use an Animal object, without anything going wrong.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Interface Segregation Principle (ISP)

A

The Interface Segregation Principle (ISP) is one of the SOLID principles of object-oriented design. It emphasizes that clients should not be forced to depend on interfaces they do not use. In simpler terms, ISP states that a class should not be forced to implement interfaces with methods it does not need.

Let’s consider a scenario where we have a large, monolithic interface called Machine that contains methods for various
machine operations such as start(), stop(), restart(), and shutdown(). However, not all machines need to support all these operations. Some machines may only need to start and stop.

ISP involves designing interfaces that are tailored to the specific needs of clients and avoiding “fat” interfaces.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Dependency Inversion Principle (DIP)

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

KISS

A

In Java, KISS can be applied by writing straightforward, understandable code without unnecessary complexity. This means avoiding overly clever solutions and keeping code concise yet clear.
Utilize built-in Java libraries and features instead of reinventing the wheel or creating overly intricate custom solutions.
Follow standard Java naming conventions and design patterns to make code more intuitive for other developers to read and understand.
Keep classes and methods focused on a single responsibility, adhering to the Single Responsibility Principle (SRP) from object-oriented design.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

DRY (DOnt repeat yourself)

A

In Java, DRY can be implemented by identifying repeating code patterns and extracting them into reusable methods or classes.
Utilize inheritance, interfaces, and composition to avoid code duplication and promote code reuse.
Create utility classes or helper methods for common tasks rather than rewriting the same logic in multiple places.
Encapsulate repetitive operations into well-named functions or classes to improve readability and maintainability.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

YAGNI (You Ain’t Gonna Need It):

A

In Java, YAGNI encourages developers to resist the temptation to add functionality prematurely. Instead, focus on delivering the required features without unnecessary additions.
Avoid over-engineering by only implementing the functionality that is currently needed to fulfill the requirements.
Refactor and extend code as new requirements arise, rather than preemptively adding complex features that may not be necessary.
Prioritize simplicity and clarity in code design, resisting the urge to add speculative features that may introduce unnecessary complexity or overhead.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Law of Demeter (LoD):

A

The Law of Demeter (LoD), also known as the principle of least knowledge or principle of least access, is a design guideline for object-oriented programming. LoD states that a module should only have knowledge of its immediate dependencies and should not reach out to access the internal details of other objects.

in spring boot case it meant that controller talks to service and not repository directly.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Single Level of Abstraction Principle (SLAP):

A

To adhere to SLAP, you could refactor the function to separate the low-level operations from the high-level operation, ensuring that each function focuses on a single level of abstraction. This improves code clarity, maintainability, and flexibility over time.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Dependency Injection (DI):

A

Dependency Injection (DI) is a design pattern used in software development to manage dependencies between components of an application. It is a technique where the dependencies of a component are provided from the outside rather than created internally. In other words, instead of a component creating its dependencies, they are “injected” into the component from an external source.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Fail Fast:

A

Fail Fast is a software development principle that promotes detecting and reporting errors as soon as they occur. Instead of allowing errors to propagate throughout the system, the application should fail immediately when an error is detected.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Rule of Three:

A

The Rule of Three suggests that if you find yourself writing similar code for the third time, you should consider refactoring it into a reusable abstraction. This principle helps in identifying common patterns and promoting code reuse and maintainability.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

What are design patterns

A

Design patterns are reusable solutions to common problems encountered in software design and development. They represent best practices and proven solutions distilled from the collective experience of software developers over time. Design patterns provide templates or blueprints for structuring code and solving specific design problems in a modular and reusable way.

20
Q

Design patterns categorization

A

Design patterns are typically categorized into three main groups based on their purpose:

Creational Patterns: These patterns deal with object creation mechanisms, providing flexible ways to create objects while hiding the creation logic from clients. Examples include Singleton, Factory Method, Abstract Factory, Builder, and Prototype.

Structural Patterns: Structural patterns focus on how classes and objects are composed to form larger structures. They help in defining relationships between objects and simplifying the structure of a system. Examples include Adapter, Composite, Proxy, Decorator, and Facade.

Behavioral Patterns: Behavioral patterns address communication between objects and how they collaborate to achieve specific tasks. They focus on interactions and responsibilities among objects, promoting flexibility and reusability. Examples include Observer, Strategy, Command, Iterator, and Template Method.

21
Q

Name the list of Creational design patterns

A

Factory Method
Abstract Factory
Builder
Prototype
Singleton

22
Q

Explain Factory Method

A

The Factory Method Pattern is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. It encapsulates the object creation logic within a method, known as the factory method, which is implemented by subclasses to instantiate objects of a specific type.

For example:
1) creating the interface of product
2) creating A and B impelementations of this interface
3) creating factory class/method where is logic in which case A or B object should be created
4) from client is able to use this factory method and delegate object creation responsibility to this.

23
Q

Abstract Factory

A

Abstract Factory Pattern is another creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. It is an extension of the Factory Method Pattern, where instead of creating individual objects, the Abstract Factory Pattern deals with creating families of related objects.

24
Q

Builder Pattern

A

The Builder Pattern is indeed a creational design pattern. It focuses on providing a way to construct complex objects step by step. This pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

Here’s an explanation of why the Builder Pattern falls under the creational design pattern category:

Object Creation:
The primary goal of the Builder Pattern is to create complex objects. It allows for the construction of objects with many configurable parameters or options.
Encapsulation of Construction Logic:
The Builder Pattern encapsulates the construction logic within a separate builder class. This class is responsible for assembling the complex object step by step, abstracting away the details of object creation from the client.
Step-by-Step Construction:
The construction process in the Builder Pattern proceeds incrementally, with each step adding specific components or configurations to the object being built. This step-by-step approach allows for greater flexibility and control over the construction process.

25
Q

Prototype pattern

A

The Prototype Pattern is a creational design pattern that focuses on creating objects by cloning an existing instance, known as a prototype, instead of creating new instances from scratch. It allows for the creation of new objects based on the properties of an existing object, providing a way to efficiently produce similar objects without the need for intricate initialization.

Copying Objects:
Imagine you have an object that you want to use as a template to create more objects with the same properties and behaviors.
Prototype Interface:
You create an interface or base class defining a method to copy itself. This method serves as a blueprint for creating copies.
Concrete Prototypes:
You create concrete classes that implement the prototype interface. Each concrete class provides its own way of copying itself.
Cloning:
When you need a new object, instead of creating it from scratch, you simply ask an existing object of the same type to clone itself. This creates a new object with the same properties and behaviors as the original.
No Need for Detailed Initialization:
Since you’re creating new objects by copying existing ones, you don’t need to go through detailed initialization steps each time. This makes object creation simpler and more efficient.
Dynamic Creation:
The Prototype Pattern allows for dynamic creation of objects at runtime. You can create new objects based on existing ones without knowing their concrete types in advance.
Flexibility and Encapsulation:
By encapsulating the cloning logic within the objects themselves, the Prototype Pattern promotes flexibility and encapsulation. Clients can create new objects without needing to know the internal details of how they are copied.

26
Q

Singleton

A

In Java, the Singleton pattern is a design pattern that ensures a class has only one instance and provides a global point of access to that instance. This pattern is useful when you want to restrict the instantiation of a class to only one object. It is commonly used for logging, caching, thread pools, database connections, and more.

This implementation ensures that only one instance of the Singleton class is created and provides a global point of access to that instance. However, it’s important to note that this basic implementation is not thread-safe. If multiple threads try to access the getInstance() method simultaneously, it could result in the creation of multiple instances. To make it thread-safe, you can use synchronization or other techniques like double-checked locking or using enum.

27
Q

Name all structural design patterns

A

Adapter Pattern: Allows objects with incompatible interfaces to work together by providing a wrapper with a compatible interface.

Bridge Pattern: Separates an object’s abstraction from its implementation so that the two can vary independently.

Composite Pattern: Composes objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Decorator Pattern: Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Facade Pattern: Provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

Flyweight Pattern: Minimizes memory usage and improves performance by sharing common parts of state between multiple objects.

Proxy Pattern: Provides a surrogate or placeholder for another object to control access to it.

28
Q

Adapter Pattern

A

The Adapter Pattern is a structural design pattern that allows objects with incompatible interfaces to collaborate. It acts as a bridge between two incompatible interfaces, making them compatible without changing their existing code.

Purpose:
The main purpose of the Adapter Pattern is to make unrelated or incompatible interfaces work together seamlessly. It enables the reuse of existing classes without modifying their source code.

How it works:
Adapter: The adapter class wraps an existing class (the “adaptee”) with a new interface that the client expects. It translates the client’s requests into calls to the adaptee’s methods.
Client: The client interacts with the adapter using the target interface. It remains unaware of the actual implementation details of the adaptee.
Adaptee: The adaptee is the existing class or interface that needs to be adapted to work with the client’s interface.

29
Q

Bridge Pattern

A

Overview:
The Bridge Pattern is a structural design pattern that decouples an abstraction from its implementation, allowing them to vary independently. It involves creating two separate hierarchies: one for the abstraction (interface or abstract class) and another for the implementation.

Purpose:
The main purpose of the Bridge Pattern is to provide a way to decouple abstraction and implementation so that changes in one won’t affect the other. It promotes flexibility and allows for easier extension and maintenance of the codebase.

How it works:
Abstraction: This defines the high-level interface that clients use. It typically contains methods that delegate to the implementation object.
Implementor: This defines the interface for concrete implementation classes. It provides an implementation for the operations defined in the abstraction.
Refined Abstraction: This extends the abstraction, providing additional functionality built on top of the basic abstraction.
Concrete Implementor: This provides concrete implementations of the operations defined by the implementor interface.

30
Q

Composite Pattern

A

The Composite Pattern is a structural design pattern that allows you to compose objects into tree structures to represent part-whole hierarchies. It enables clients to treat individual objects and groups of objects uniformly.

Purpose:
The main purpose of the Composite Pattern is to represent hierarchical structures of objects in a way that allows clients to work with individual objects and collections of objects in a consistent manner. It helps in building complex structures from simple parts.

How it works:
Component: This is the base interface or abstract class that defines common methods for both simple and complex objects in the hierarchy.
Leaf: This represents the individual objects in the hierarchy. They implement the Component interface and represent the “leaf” nodes of the tree structure.
Composite: This represents the complex objects composed of one or more simpler objects. They also implement the Component interface and can contain child components.

31
Q

Decorator pattern

A

The Decorator Pattern is a structural design pattern that allows you to add new functionality to an object dynamically without altering its structure. It is used to extend or modify the behavior of individual objects at runtime.

The main purpose of the Decorator Pattern is to provide a flexible alternative to subclassing for extending the functionality of objects. It allows behavior to be added to individual objects without affecting the behavior of other objects from the same class.

32
Q

Facade Pattern

A

The Facade Pattern is a structural design pattern that provides a simplified interface to a complex system, hiding its complexities from clients. It serves as a “facade” or entry point to a group of interfaces in a subsystem.

Purpose:
The main purpose of the Facade Pattern is to provide a unified interface to a set of interfaces in a subsystem, making it easier to use. It simplifies the interaction between clients and complex systems by providing a higher-level interface.

33
Q

Flyweight Pattern

A

Overview:
The Flyweight Pattern is a structural design pattern that aims to minimize memory usage or computational expenses by sharing as much as possible with similar objects. It achieves this by storing common state externally and passing it to the objects instead of storing it internally.

Purpose:
The main purpose of the Flyweight Pattern is to optimize the use of resources, especially when dealing with a large number of similar objects. It allows you to reduce memory consumption and improve performance by sharing common state among multiple objects.

34
Q

proxy pattern

A

Overview:
The Proxy Pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. It acts as an intermediary between the client and the real object, allowing the proxy to add additional functionality such as lazy initialization, access control, or logging.

Purpose:
The main purpose of the Proxy Pattern is to control access to an object, adding a layer of indirection between the client and the real object. It allows you to manage the creation, access, and behavior of the real object without the client needing to be aware of it.

35
Q

Name all behavioral design patterns

A

Chain of Responsibility Pattern
Command Pattern
Interpreter Pattern
Iterator Pattern
Mediator Pattern
Memento Pattern
Observer Pattern
State Pattern
Strategy Pattern
Template Method Pattern
Visitor Pattern

36
Q

Chain of Responsibility Pattern

A

Overview:
The Chain of Responsibility Pattern is a behavioral design pattern that allows you to pass a request through a series of handlers, where each handler can decide whether to process the request or pass it on to the next handler in the chain. It promotes loose coupling and flexibility by decoupling senders of requests from receivers.

Purpose:
The main purpose of the Chain of Responsibility Pattern is to decouple senders and receivers of requests, allowing multiple objects to have a chance to handle the request without the sender needing to know which object will handle it. It provides a flexible way to process requests dynamically at runtime.

37
Q

Command Pattern

A

The Command Pattern is a behavioral design pattern that encapsulates a request as an object, thereby allowing for parameterization of clients with queues, requests, and operations. It decouples the sender of a request from its receiver, allowing you to parameterize clients with queues, requests, and operations, support undoable operations, and provide a framework for scheduling operations.

Here’s a simplified explanation:

Overview:
Sender (Client): Initiates requests but does not know how they will be handled or executed.
Receiver: Knows how to carry out the operation associated with a request.
Command: Encapsulates a request as an object, containing all the necessary information to perform the action when executed.
Invoker: Holds a reference to a command object and can execute the command when requested.
Purpose:
Decoupling: It separates the sender of a request from its receiver, allowing each to vary independently.
Encapsulation: It encapsulates a request as an object, providing a uniform interface to interact with commands.
Undo/Redo: It supports undoable operations by providing methods to revert executed commands.
Example:
Consider a remote control for a television. Instead of directly controlling the television, each button on the remote control represents a command object (e.g., TurnOnCommand, TurnOffCommand, ChangeChannelCommand). When a button is pressed, the remote control invokes the corresponding command, which in turn executes the operation on the television (receiver).

38
Q

Iterator design pattern

A

Pattern is indeed a behavioral design pattern that provides a way to access the elements of a collection sequentially without exposing its underlying structure. Here’s a simplified explanation:

Overview:
The Iterator Pattern allows you to access elements of a collection (such as lists, arrays, trees) sequentially without needing to know how the collection is implemented internally. It separates the traversal algorithm from the collection, providing a uniform interface for iterating over different types of collections.

Key Components:
Iterator: Defines an interface for accessing elements of a collection. It typically includes methods like hasNext() to check if there are more elements and next() to retrieve the next element.
Concrete Iterator: Implements the iterator interface and keeps track of the current position in the collection. It provides methods to traverse the collection and retrieve elements.
Aggregate/Collection: Defines an interface for creating an iterator object. It typically includes a method to create an iterator instance.
Concrete Aggregate: Implements the collection interface and provides an implementation for creating a specific iterator object that can traverse the collection.

39
Q

Mediator Pattern

A

The Mediator Pattern is indeed a behavioral design pattern that facilitates communication between objects by encapsulating the interaction logic within a mediator object. Here’s a simplified explanation:

Overview:
The Mediator Pattern promotes loose coupling by reducing direct dependencies between objects and centralizing communication through a mediator object. It helps organize complex communication flows between multiple objects by providing a central point of control.

Key Components:
Mediator: Defines an interface for communicating with colleague objects. It encapsulates the communication logic and keeps track of colleague objects.
Concrete Mediator: Implements the mediator interface and coordinates communication between colleague objects. It knows about all the colleague objects and routes messages between them.
Colleague: Represents objects that communicate with each other through the mediator. Colleague objects are typically unaware of each other and communicate only through the mediator.
Example:
Consider a chat application where multiple users interact with each other. Instead of users directly communicating with each other, their messages are sent through a chat room (mediator). The chat room receives messages from users and forwards them to the appropriate recipients, ensuring that users are decoupled from each other.

Mediator is a behavioral design pattern that lets you reduce
chaotic dependencies between objects. The pattern restricts
direct communications between the objects and forces them to
collaborate only via a mediator object

40
Q

Memento Design pattern

A

The Memento Pattern is indeed a behavioral design pattern that allows you to capture and restore the internal state of an object without exposing its implementation details. Here’s a simplified explanation:

Overview:
The Memento Pattern provides a way to capture an object’s internal state at a particular moment and store it externally. This stored state, known as a memento, can later be used to restore the object to its previous state. It’s particularly useful for implementing undo functionality or managing checkpoints in an application.

41
Q

Observer is a behavioral design pattern

A

Observer is a behavioral design pattern that lets you define a
subscription mechanism to notify multiple objects about any
events that happen to the object they’re observing.

The Observer Pattern is a behavioral design pattern that establishes a one-to-many dependency between objects, such that when one object (the subject) changes its state, all its dependents (observers) are notified and updated automatically. Here’s a simplified explanation:

Overview:
The Observer Pattern allows multiple observer objects to subscribe to changes in a subject object. When the state of the subject changes, it notifies all its observers, triggering them to update themselves accordingly. This pattern enables loose coupling between objects and promotes the principle of “don’t call us, we’ll call you”.

Key Components:
Subject (Observable): Represents the object being observed. It maintains a list of its dependents (observers) and provides methods to subscribe and unsubscribe observers, as well as to notify them of changes.
Observer: Defines an interface for objects that should be notified of changes in the subject. It typically includes a method like update() that is called by the subject when a change occurs.
Concrete Subject: Implements the subject interface and maintains the state of interest. It sends notifications to its observers whenever its state changes.
Concrete Observer: Implements the observer interface and receives notifications from the subject. It updates itself based on the information received from the subject.
Example:
Consider a weather monitoring system where multiple displays (observers) want to be notified of changes in weather conditions (subject). Each display subscribes to the weather station to receive updates. When the weather station detects a change in weather, it notifies all subscribed displays, which then update themselves to reflect the new weather information.

42
Q

State behavioral design pattern

A

State is a behavioral design pattern that lets an object alter its
behavior when its internal state changes. It appears as if the
object changed its class.

The State Pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. It achieves this by encapsulating each state as an object and delegating state-specific behavior to these state objects. Here’s a simplified explanation:

Overview:
The State Pattern allows an object to change its behavior at runtime by delegating the responsibility for behavior to different state objects. It’s particularly useful when an object’s behavior depends on its internal state and needs to change dynamically as the state changes.

Key Components:
Context: Represents the object whose behavior changes based on its internal state. It maintains a reference to the current state object and provides methods to set and get the state.
State: Defines an interface for encapsulating the behavior associated with a particular state of the context. It typically includes methods for handling various events or operations.
Concrete State: Implements the state interface and provides behavior specific to a particular state of the context. Each concrete state object encapsulates the behavior for a specific state of the context.
Example:
Consider a vending machine that dispenses different items based on its current state (e.g., has coins, item selected). The vending machine’s behavior (dispensing items, returning change) changes depending on its internal state. Using the State Pattern, each state of the vending machine (e.g., HasCoinsState, SoldState) is represented by a separate state object, which encapsulates the behavior associated with that state.

43
Q

Strategy pattern

A

The Strategy Pattern is indeed a behavioral design pattern that allows you to define a family of algorithms, encapsulate each algorithm into a separate class, and make the objects of these classes interchangeable. Here’s a simplified explanation:

Overview:
The Strategy Pattern enables you to define a set of algorithms, encapsulate each algorithm into its own class, and make these algorithms interchangeable within a context object. It allows the client to select a specific algorithm at runtime without modifying the client’s code.

Key Components:
Strategy Interface: Defines a common interface for all algorithms. It typically declares a method or set of methods that represent the algorithm’s behavior.
Concrete Strategies: Implement the strategy interface and provide specific implementations for each algorithm. Each concrete strategy encapsulates a different algorithm.
Context: Represents the object that uses the strategy. It maintains a reference to a strategy object and provides methods to set and execute the strategy.
Example:
Consider a sorting algorithm where different strategies (e.g., Bubble Sort, Quick Sort, Merge Sort) can be used to sort a list of elements. Using the Strategy Pattern, each sorting algorithm is encapsulated into its own class (concrete strategy). The context object (e.g., a sorting utility) can be configured with a specific sorting algorithm at runtime, allowing the client to switch between sorting strategies easily.

44
Q

Template Method

A

Template Method is a behavioral design pattern that defines
the skeleton of an algorithm in the superclass but lets
subclasses override specific steps of the algorithm without
changing its structure

The Template Method Pattern is indeed a behavioral design pattern that defines the skeleton of an algorithm in a superclass but allows subclasses to override specific steps of the algorithm without changing its overall structure. Here’s a simplified explanation:

Overview:
The Template Method Pattern defines the basic structure of an algorithm in a superclass, with some steps implemented directly and others deferred to subclasses. Subclasses can provide concrete implementations for the deferred steps, customizing the behavior of the algorithm without altering its overall structure.

Key Components:
Abstract Class (Template): Defines the template method, which is the skeleton of the algorithm. It contains abstract methods (called hooks) that represent steps of the algorithm to be implemented by subclasses.
Concrete Subclasses: Implement the abstract methods defined in the abstract class to provide concrete implementations for specific steps of the algorithm. They customize the behavior of the algorithm without changing its overall structure.
Example:
Consider a process for preparing different types of beverages, such as tea and coffee. The abstract class defines a template method for preparing beverages, which includes steps common to all beverages (e.g., boiling water, adding ingredients). Subclasses (e.g., Tea, Coffee) override specific steps (e.g., adding tea leaves, adding coffee powder) to customize the preparation process for each type of beverage.

45
Q

visitor pattern

A

The Visitor Pattern is a behavioral design pattern that enables you to define new operations without changing the classes of the elements on which it operates. It achieves this by separating the algorithms from the object structure, allowing you to add new operations or behaviors to existing classes without modifying their code. Here’s a simplified explanation:

Overview:
The Visitor Pattern allows you to define operations to be performed on elements of an object structure without changing the classes of those elements. It achieves this by separating the operations (visitor) from the elements (visited) and providing a mechanism for the visitor to traverse the object structure.

Key Components:
Visitor: Defines a visit method for each element type in the object structure. Visitors encapsulate operations to be performed on elements.
Concrete Visitor: Implements the visitor interface and provides concrete implementations for each visit method. It contains the logic for performing operations on elements.
Element: Defines an accept method that accepts a visitor as an argument. Elements provide a way for visitors to access and operate on them.
Concrete Element: Implements the element interface and provides concrete implementations for the accept method. Each concrete element type accepts visitors and delegates operations to them.
Object Structure: Represents the collection or structure of elements to be visited. It provides methods to iterate over elements and accept visitors.
Example:
Consider a scenario where you have a document structure consisting of different types of elements (e.g., paragraphs, headings, images). You can use the Visitor Pattern to define operations like printing, formatting, or analyzing the document. Each element type implements an accept method to accept visitors, and visitors implement visit methods for each element type to perform operations.