Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ set(APP_SOURCES
"src/patterns/behavioral/State.cpp"
"src/patterns/behavioral/Observer.cpp"
"src/patterns/creational/Singleton.cpp"
"src/patterns/creational/FactoryMethod.cpp"
)

# Test files
Expand Down
4 changes: 4 additions & 0 deletions docs/uml/patterns_creational_factorymethod.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
103 changes: 103 additions & 0 deletions src/patterns/behavioral/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Behavioral Design Patterns

Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects.

---

## Chain of Responsibility

**Chain of Responsibility**
Lets you pass requests along a chain of handlers. Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain.

**Real-time example:**
Customer support tickets in a company. Simple requests go to the first-level support, more complex issues go to specialists, and only very complex issues reach managers.

---

## Command

**Command**
Turns a request into a stand-alone object that contains all information about the request. This lets you pass requests as arguments, delay or queue execution, and support undo operations.

**Real-time example:**
Using a remote control for smart home devices. Each button press represents a command: turn on lights, open curtains, or play music. You can even undo the last command.

---

## Iterator

**Iterator**
Lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.).

**Real-time example:**
Browsing a photo gallery app. You can swipe left or right to view photos without knowing how the photos are stored internally.

---

## Mediator

**Mediator**
Reduces chaotic dependencies between objects by forcing them to communicate through a mediator.

**Real-time example:**
An air traffic control tower. Planes don’t communicate directly with each other; the tower coordinates landings and takeoffs.

---

## Memento

**Memento**
Lets you save and restore the previous state of an object without revealing its implementation details.

**Real-time example:**
The “Undo” feature in a text editor. You can revert to a previous version of your document without knowing the details of how the editor stores text internally.

---

## Observer

**Observer**
Defines a subscription mechanism to notify multiple objects about events happening to the object they’re observing.

**Real-time example:**
Social media notifications. When someone posts a new photo, all their followers are notified immediately.

---

## State

**State**
Lets an object alter its behavior when its internal state changes, making it appear as if the object changed its class.

**Real-time example:**
A traffic light. Its behavior (red, yellow, green) changes automatically depending on its current state.

---

## Strategy

**Strategy**
Defines a family of algorithms, puts each into a separate class, and makes them interchangeable.

**Real-time example:**
A navigation app lets you choose between driving, walking, or cycling routes. Each strategy calculates a different route but uses the same interface.

---

## Template Method

**Template Method**
Defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps without changing its structure.

**Real-time example:**
Making coffee or tea in a café. The steps (boil water, pour, serve) are the same, but each drink has slightly different preparation steps.

---

## Visitor

**Visitor**
Lets you separate algorithms from the objects on which they operate.

**Real-time example:**
A tax calculator that processes different types of items (books, electronics, groceries) without changing the item classes. The calculator “visits” each item to compute tax.
174 changes: 174 additions & 0 deletions src/patterns/creational/FactoryMethod.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// cppcheck-suppress-file [functionStatic]

// Factory Method 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.
// Appicability:
// (*) when you don’t know beforehand the exact types and dependencies of the objects your code should work with.
// (**) when you want to provide users of your library or framework with a way to extend its internal components.
// (***)when you want to save system resources by reusing existing objects instead of rebuilding them each time.

// UML: docs/uml/patterns_creational_factorymethod.drawio.svg

#include <iostream>
#include <string>
namespace
{
namespace FactoryMethod
{
/**
* The Product interface declares the operations that all concrete products must
* implement.
*/
class IGdbProduct
{
public:
virtual ~IGdbProduct() = default;
virtual void launch() const = 0;
};

/**
* Concrete Products provide various implementations of the Product interface.
*/
class LinuxGdbProduct : public IGdbProduct
{
public:
void launch() const override
{
std::cout
<< "\tsudo apt update && sudo apt install -y gdb && gdb --version\n";
}
};

class WindowsGdbProduct : public IGdbProduct
{
public:
void launch() const override
{
std::cout << "\tpacman -Syu mingw-w64-x86_64-gdb && gdb --version\n";
}
};

class MacOsGdbProduct : public IGdbProduct
{
public:
void launch() const override
{
std::cout << "\tbrew install gdb && gdb --version\n";
}
};

/**
* The Creator class declares the factory method that is supposed to return an
* object of a Product class. The Creator's subclasses usually provide the
* implementation of this method.
*/
class IGdbCreator
{
public:
virtual ~IGdbCreator() = default;
virtual IGdbProduct *factoryMethod() = 0;
virtual void launchGdb() = 0;
};

class AbstractGdbCreater : public IGdbCreator
{
public:
// Call the factory method to create a Product object.

void launchGdb() override final
{
IGdbProduct *gdb = this->factoryMethod();
gdb->launch();
delete gdb;
}
};

/**
* Concrete Creators override the factory method in order to change the
* resulting product's type.
*/
class WindowsGdbCreator : public AbstractGdbCreater
{
public:
IGdbProduct *factoryMethod() override
{
return new WindowsGdbProduct();
}
};

class LinuxGdbCreator : public AbstractGdbCreater
{
public:
IGdbProduct *factoryMethod() override
{
return new LinuxGdbProduct();
}
};

class MacOsGdbCreator : public AbstractGdbCreater
{
public:
IGdbProduct *factoryMethod() override
{
return new MacOsGdbProduct();
}
};

/**
* The client code works with an instance of a concrete creator, albeit through its base interface.
* As long as the client keeps working with the creator via the base interface, you can pass it any creator's subclass.
*/
namespace ClientCode
{
void clientCode(IGdbCreator *gdb)
{
if (gdb != nullptr)
gdb->launchGdb();
}
}

class GdbCreatorFactory
{
public:
static IGdbCreator *createGdbCreator(const std::string &os)
{
if (os == "linux")
{
return new LinuxGdbCreator();
}
else if (os == "windows")
{
return new WindowsGdbCreator();
}
else if (os == "macos")
{
return new MacOsGdbCreator();
}
else
{
std::cout << "OS not support yet - " << os << "\n";
return nullptr;
}
}
};

void run()
{
std::string os = "linux";
IGdbCreator *gdb = GdbCreatorFactory::createGdbCreator(os);
ClientCode::clientCode(gdb);
delete gdb;
}
}
}

struct FactoryMethodAutoRunner
{
FactoryMethodAutoRunner()
{
std::cout << "\n--- FactoryMethod Pattern Example ---\n";
FactoryMethod::run();
}
};

static FactoryMethodAutoRunner instance;
53 changes: 53 additions & 0 deletions src/patterns/creational/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Creational Design Patterns

Creational design patterns provide various object creation mechanisms, which increase flexibility and reuse of existing code.

---

## Factory Method

**Factory Method**
Provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.

**Real-time example:**
A ride-hailing app can create different types of rides: economy, premium, or SUV. The app defines a general interface for booking a ride, and the specific ride type is decided at runtime.

---

## Abstract Factory

**Abstract Factory**
Lets you produce families of related objects without specifying their concrete classes.

**Real-time example:**
A furniture store app that sells sets of furniture. If a customer chooses a "Modern" style, the app provides a matching chair, table, and sofa. If "Victorian" style is chosen, it provides a different matching set. The app doesn’t need to know the concrete classes of each furniture piece.

---

## Builder

**Builder**
Lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.

**Real-time example:**
Ordering a custom pizza online. You can choose the dough, sauce, toppings, and size step by step, resulting in different pizzas, all using the same ordering process.

---

## Prototype

**Prototype**
Lets you copy existing objects without making your code dependent on their classes.

**Real-time example:**
Copying a template for a new document in Google Docs. Instead of creating a document from scratch, you duplicate an existing one and modify it.

---

## Singleton

**Singleton**
Lets you ensure that a class has only one instance, while providing a global access point to this instance.

**Real-time example:**
A system configuration manager in an app. All parts of the app access the same configuration instance, so settings are consistent across the application.
2 changes: 2 additions & 0 deletions src/patterns/creational/Singleton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// (*) when a class in your program should have just a single instance available to all clients; for example, a single database object shared by different parts of the program.
// (**) when you need stricter control over global variables.

// UML: docs/uml/patterns_creational_singleton.drawio.svg

#include <iostream>

namespace
Expand Down
Loading