From 2219ec895f1e539b85267d53d513c12fac1bae12 Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Tue, 25 Nov 2025 08:46:37 +0700 Subject: [PATCH 1/3] Add README files for the patterns --- src/patterns/behavioral/README.md | 103 ++++++++++++++++++++++++++++++ src/patterns/creational/README.md | 53 +++++++++++++++ src/patterns/structural/README.md | 73 +++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 src/patterns/behavioral/README.md create mode 100644 src/patterns/creational/README.md create mode 100644 src/patterns/structural/README.md diff --git a/src/patterns/behavioral/README.md b/src/patterns/behavioral/README.md new file mode 100644 index 0000000..47dcbb3 --- /dev/null +++ b/src/patterns/behavioral/README.md @@ -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. diff --git a/src/patterns/creational/README.md b/src/patterns/creational/README.md new file mode 100644 index 0000000..cc89aa1 --- /dev/null +++ b/src/patterns/creational/README.md @@ -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. diff --git a/src/patterns/structural/README.md b/src/patterns/structural/README.md new file mode 100644 index 0000000..a630b45 --- /dev/null +++ b/src/patterns/structural/README.md @@ -0,0 +1,73 @@ +# Structural Design Patterns + +Structural design patterns explain how to assemble objects and classes into larger structures, while keeping these structures flexible and efficient. + +--- + +## Adapter + +**Adapter** +Allows objects with incompatible interfaces to collaborate. + +**Real-time example:** +A travel power adapter. You plug a device from one country into a socket in another country using an adapter to make it compatible. + +--- + +## Bridge + +**Bridge** +Lets you split a large class or a set of closely related classes into two separate hierarchies—abstraction and implementation—which can be developed independently. + +**Real-time example:** +A remote control system. The remote (abstraction) can control different devices (TV, AC, music system) independently without changing the remote design. + +--- + +## Composite + +**Composite** +Lets you compose objects into tree structures and then work with these structures as if they were individual objects. + +**Real-time example:** +A company organizational chart. Managers and employees are treated uniformly. A manager can have subordinates, who can also be managers or employees. + +--- + +## Decorator + +**Decorator** +Lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors. + +**Real-time example:** +Adding extra features to a coffee order. You start with a plain coffee and decorate it with milk, sugar, or flavors without changing the original coffee class. + +--- + +## Facade + +**Facade** +Provides a simplified interface to a library, a framework, or any other complex set of classes. + +**Real-time example:** +A home automation app. Instead of controlling lights, thermostat, and security system separately, the app provides a single interface to manage everything easily. + +--- + +## Flyweight + +**Flyweight** +Lets you fit more objects into available memory by sharing common parts of state between multiple objects. + +**Real-time example:** +In a word processor, the same font style and size is shared across multiple characters instead of storing them individually for every character. + +--- + +## Proxy + +**Proxy** +Lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something before or after the request reaches the original object. + +**Real-time example:** +A payment gateway proxy. Instead of paying directly to the bank, you use a payment service that validates, logs, and then forwards your request to the bank. From 1f17733bcebeda9900412e30a26444edb2cfadc9 Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Tue, 25 Nov 2025 12:26:27 +0700 Subject: [PATCH 2/3] Add the FactoryMethod pattern --- CMakeLists.txt | 1 + ...tterns_creational_factorymethod.drawio.svg | 4 + src/patterns/creational/FactoryMethod.cpp | 173 ++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 docs/uml/patterns_creational_factorymethod.drawio.svg create mode 100644 src/patterns/creational/FactoryMethod.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d6ab1c1..27acf4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/docs/uml/patterns_creational_factorymethod.drawio.svg b/docs/uml/patterns_creational_factorymethod.drawio.svg new file mode 100644 index 0000000..37de042 --- /dev/null +++ b/docs/uml/patterns_creational_factorymethod.drawio.svg @@ -0,0 +1,4 @@ + + + +
Client
+ clientCode(IGdbCreator* creator): type
main:
{
 IGdbCreator* creator= new WindowsGdbCreator();
 clientCode(creator);
}

clientCode:
{
creator->launch();
}

<<Interface>>
IGdbProduct


+ method(Type): Type

+ launch(): Type

LinuxGdbProduct
+ field: type
+ launch(): Type
WindowGdbProduct
+ field: type
+ launch(): Type
MacOsGdbProduct
+ field: type
+ launch(): Type

<<Interface>>
IGdbCreator


+ factoryMethod(Type): IGdbProduct*

+ launch(): Type

<<Abstract>>
AbstractGdbCreator


+ launch(): Type

LinuxGdbCreator
+ field: type

+ factoryMethod(Type): IGdbProduct*


WindowsGdbCreator
+ field: type

+ factoryMethod(Type): IGdbProduct*


MacOsGdbCreator
+ field: type

+ factoryMethod(Type): IGdbProduct*


1
Extends
Extends
Extends
Use
lauch:
{
// execute the complex logics
pacman -Syu mingw-w64-x86_64-gdb && gdb --version
}
lauch:
{
IGdbProduct* gdb = this-> templateMethod();
if(gdb != nullptr){
 gdb->launch();
 delete gdb;
 }
}
factoryMethod:
{
 // to create the concrete product 
 return new MacOsGdbProduct();
}
\ No newline at end of file diff --git a/src/patterns/creational/FactoryMethod.cpp b/src/patterns/creational/FactoryMethod.cpp new file mode 100644 index 0000000..530dc1f --- /dev/null +++ b/src/patterns/creational/FactoryMethod.cpp @@ -0,0 +1,173 @@ +// 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 +#include +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; \ No newline at end of file From 05030a545c03d02f745404af16ca449782dc1bbf Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Tue, 25 Nov 2025 12:27:18 +0700 Subject: [PATCH 3/3] fix doc issue --- src/patterns/creational/FactoryMethod.cpp | 1 + src/patterns/creational/Singleton.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/patterns/creational/FactoryMethod.cpp b/src/patterns/creational/FactoryMethod.cpp index 530dc1f..10766b3 100644 --- a/src/patterns/creational/FactoryMethod.cpp +++ b/src/patterns/creational/FactoryMethod.cpp @@ -6,6 +6,7 @@ // (*) 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 diff --git a/src/patterns/creational/Singleton.cpp b/src/patterns/creational/Singleton.cpp index 2f15072..449c9fc 100644 --- a/src/patterns/creational/Singleton.cpp +++ b/src/patterns/creational/Singleton.cpp @@ -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 namespace