21 |
22 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Iterator/README.md:
--------------------------------------------------------------------------------
1 | Iterator is a behavioral design pattern that lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.).
2 |
3 | # Conceptual Example:
4 | This example illustrates the structure of the Abstract Factory design pattern. It focuses on answering these questions:
5 | * What classes does it consist of?
6 | * What roles do these classes play?
7 | * In what way the elements of the pattern are related?
8 |
9 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
10 |
11 | # Real World Example:
12 | ## AccesCSV
13 | This example of the Iterator pattern provides easy access to CSV files.
14 |
15 | ## Book and User Iterator
16 | In both examples, we define an iterator that allows the client to traverse through collections (books or users) while keeping the collection encapsulated and providing an easy interface for iteration.
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ### LICENSE (MIT License)
2 |
3 | ```markdown
4 | MIT License
5 |
6 | Copyright (c) 2024 JawherKl
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Iterator/PHP/RealWorldExample/BookIterator.php:
--------------------------------------------------------------------------------
1 | books = $books;
16 | }
17 |
18 | public function rewind(): void
19 | {
20 | $this->currentIndex = 0;
21 | }
22 |
23 | public function current(): mixed
24 | {
25 | return $this->books[$this->currentIndex];
26 | }
27 |
28 | public function key(): int
29 | {
30 | return $this->currentIndex;
31 | }
32 |
33 | public function next(): void
34 | {
35 | ++$this->currentIndex;
36 | }
37 |
38 | public function valid(): bool
39 | {
40 | return isset($this->books[$this->currentIndex]);
41 | }
42 | }
43 |
44 | /**
45 | * The client code.
46 | */
47 | $books = [
48 | 'The Catcher in the Rye',
49 | 'To Kill a Mockingbird',
50 | '1984',
51 | 'Pride and Prejudice'
52 | ];
53 |
54 | $bookIterator = new BookIterator($books);
55 |
56 | foreach ($bookIterator as $index => $book) {
57 | echo "Book {$index}: {$book}\n";
58 | }
59 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Iterator/PHP/RealWorldExample/UserIterator.php:
--------------------------------------------------------------------------------
1 | users = $users;
16 | }
17 |
18 | public function rewind(): void
19 | {
20 | $this->currentIndex = 0;
21 | }
22 |
23 | public function current(): mixed
24 | {
25 | return $this->users[$this->currentIndex];
26 | }
27 |
28 | public function key(): int
29 | {
30 | return $this->currentIndex;
31 | }
32 |
33 | public function next(): void
34 | {
35 | ++$this->currentIndex;
36 | }
37 |
38 | public function valid(): bool
39 | {
40 | return isset($this->users[$this->currentIndex]);
41 | }
42 | }
43 |
44 | /**
45 | * The client code.
46 | */
47 | $users = [
48 | ['id' => 1, 'name' => 'John Doe'],
49 | ['id' => 2, 'name' => 'Jane Smith'],
50 | ['id' => 3, 'name' => 'Emily Johnson']
51 | ];
52 |
53 | $userIterator = new UserIterator($users);
54 |
55 | foreach ($userIterator as $index => $user) {
56 | echo "User {$index}: ID: {$user['id']}, Name: {$user['name']}\n";
57 | }
58 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/README.md:
--------------------------------------------------------------------------------
1 | Abstract Factory is a creational design pattern, which solves the problem of creating entire product families without specifying their concrete classes.
2 |
3 | # Conceptual Example:
4 | This example illustrates the structure of the Abstract Factory design pattern. It focuses on answering these questions:
5 | * What classes does it consist of?
6 | * What roles do these classes play?
7 | * In what way the elements of the pattern are related?
8 |
9 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
10 |
11 | # Real World Example:
12 | ## Web Template:
13 | In this example, the Abstract Factory pattern provides an infrastructure for creating various types of templates for different elements of a web page.
14 |
15 | A web application can support different rendering engines at the same time, but only if its classes are independent of the concrete classes of rendering engines. Hence, the application’s objects must communicate with template objects only via their abstract interfaces. Your code shouldn’t create the template objects directly, but delegate their creation to special factory objects. Finally, your code shouldn’t depend on the factory objects either but, instead, should work with them via the abstract factory interface.
16 |
17 |
--------------------------------------------------------------------------------
/patterns/Behavioral/State/README.md:
--------------------------------------------------------------------------------
1 | State is a behavioral design pattern that allows an object to change the behavior when its internal state changes.
2 |
3 | The pattern extracts state-related behaviors into separate state classes and forces the original object to delegate the work to an instance of these classes, instead of acting on its own.
4 |
5 |
6 |
7 |
8 |
9 | # RealWorldExample:
10 | ## OrderProcess:
11 | In this example, we simulate a simple Order Process where an order can be in one of several states: New, Shipped, or Delivered. The Order class changes its behavior depending on the current state.
12 |
13 | ### Explanation:
14 |
15 | 1. **OrderState Interface**:
16 | - The `OrderState` interface defines the `handleOrder()` method, which is implemented by each concrete state to handle the order in that specific state.
17 |
18 | 2. **Concrete States**:
19 | - `NewOrderState`: The order is new, and the action transitions the order to the `ShippedOrderState`.
20 | - `ShippedOrderState`: The order is shipped, and the action transitions the order to the `DeliveredOrderState`.
21 | - `DeliveredOrderState`: The order has been delivered, and no further state transitions occur.
22 |
23 | 3. **Order Class (Context)**:
24 | - The `Order` class holds the current state and allows transitions between states using the `setState()` method. The `processOrder()` method delegates the behavior to the current state.
25 |
26 | 4. **Client Code**:
27 | - In the client code, we create an `Order` object, and then we call `processOrder()` to simulate the order's journey from `New` to `Shipped` to `Delivered`.
28 |
29 | ### Output:
30 |
31 | ```
32 | Processing the order:
33 | Order is new. Processing the order.
34 | Order has been shipped. Waiting for delivery.
35 | Order has been delivered. Thank you for your purchase!
36 | ```
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/README.md:
--------------------------------------------------------------------------------
1 | Singleton is a creational design pattern, which ensures that only one object of its kind exists and provides a single point of access to it for any other code.
2 |
3 | # Conceptual Example:
4 | This example illustrates the structure of the Singleton design pattern and focuses on the following questions:
5 | * What classes does it consist of?
6 | * What roles do these classes play?
7 | * In what way the elements of the pattern are related?
8 |
9 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
10 |
11 | # Real World Example:
12 | ## Global Logging:
13 | The Singleton pattern is notorious for limiting code reuse and complicating unit testing. However, it’s still very useful in some cases. In particular, it’s handy when you need to control some shared resources. For example, a global logging object that has to control the access to a log file. Another good example: a shared runtime configuration storage.
14 |
15 | ## Database Connection
16 | This example creates a singleton for managing a database connection, ensuring only one instance is used throughout the application.
17 | DatabaseConnection: Manages a single database connection instance.
18 |
19 | ## Application Settings
20 | This example demonstrates a singleton for application settings, allowing global access to configuration values.
21 | AppSettings: Manages global application settings, ensuring consistent access across the application.
22 |
23 | ## Cache Manager Singleton
24 | This example implements a singleton for managing a cache, ensuring a single instance handles cache storage.
25 | CacheManager: Handles caching of data, providing a single point of access to cache resources.
26 |
27 | These examples illustrate how the Singleton pattern can be applied to various scenarios where a single instance of a class is beneficial.
--------------------------------------------------------------------------------
/patterns/Structural/Decorator/README.md:
--------------------------------------------------------------------------------
1 | Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.
2 |
3 | Wearing clothes is an example of using decorators. When you’re cold, you wrap yourself in a sweater. If you’re still cold with a sweater, you can wear a jacket on top. If it’s raining, you can put on a raincoat. All of these garments “extend” your basic behavior but aren’t part of you, and you can easily take off any piece of clothing whenever you don’t need it.
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Bridge design pattern and focuses on the following questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## TextFilering
15 | In this example, the Decorator pattern helps you to construct complex text filtering rules to clean up content before rendering it on a web page. Different types of content, such as comments, forum posts or private messages require different sets of filters.
16 |
17 | ## MessageTransformation
18 | In this case, we'll decorate a basic Message class to add various text transformations like encryption, reversing, and uppercasing.
19 |
20 | ### Explanation:
21 | * Component Interface (Message): Declares getText() method for processing text.
22 | * Concrete Component (SimpleMessage): Implements the interface to return the original message.
23 | * Base Decorator (MessageDecorator):
24 | Implements the same interface and holds a reference to a Message object.
25 | * Concrete Decorators:
26 | -ReverseTextDecorator: Reverses the text.
27 | -UppercaseDecorator: Converts text to uppercase.
28 | -EncryptionDecorator: Applies ROT13 encryption.
29 | * Client Code:
30 | Demonstrates the dynamic composition of decorators to modify the message.
31 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/Go/Singleton.go:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Implementation Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern, which ensures a
6 | | class has only one instance and provides a global point of access to it.
7 | |--------------------------------------------------------------------------
8 | | @category Design Pattern
9 | | @package Creational/Singleton
10 | | @version 1.0.0
11 | | @license MIT License
12 | | @link https://github.com/JawherKl/design-patterns-in-go
13 | |--------------------------------------------------------------------------
14 | |
15 | | Key Components:
16 | | 1. **Singleton Class**: Implements the `getInstance` method for managing
17 | | the single instance.
18 | | 2. **Static Instance Storage**: Ensures only one instance per subclass.
19 | | 3. **Client Code**: Demonstrates that the same instance is returned.
20 | |
21 | | Use Case:
22 | | Use the Singleton pattern when only one instance of a class should exist,
23 | | such as in managing database connections or configuration settings.
24 | */
25 |
26 | package main
27 |
28 | import (
29 | "fmt"
30 | "sync"
31 | )
32 |
33 | type Singleton struct {
34 | // Define the Singleton's properties here
35 | }
36 |
37 | var instance *Singleton
38 | var mu sync.Mutex
39 |
40 | // GetInstance ensures that only one instance of the Singleton class is created
41 | func GetInstance() *Singleton {
42 | mu.Lock()
43 | defer mu.Unlock()
44 |
45 | if instance == nil {
46 | instance = &Singleton{}
47 | }
48 | return instance
49 | }
50 |
51 | func (s *Singleton) SomeBusinessLogic() {
52 | // Add your business logic here
53 | }
54 |
55 | func main() {
56 | s1 := GetInstance()
57 | s2 := GetInstance()
58 |
59 | if s1 == s2 {
60 | fmt.Println("Singleton works, both variables contain the same instance.")
61 | } else {
62 | fmt.Println("Singleton failed, variables contain different instances.")
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/patterns/Structural/Composite/README.md:
--------------------------------------------------------------------------------
1 | Composite is a structural design pattern that lets you compose objects into tree structures and then work with these structures as if they were individual objects.
2 |
3 | Composite became a pretty popular solution for the most problems that require building a tree structure. Composite’s great feature is the ability to run methods recursively over the whole tree structure and sum up the results.
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Bridge design pattern and focuses on the following questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## HTMLDOMTree
15 | The HTML DOM tree is an example of such a structure. For instance, while the various input elements can act as leaves, the complex elements like forms and fieldsets play the role of composites.
16 |
17 | ## FileSystem
18 | example of the Composite Design Pattern similar to the provided one. It demonstrates the structure and functionality of a filesystem (files and folders) using the pattern.
19 |
20 | ### Explanation:
21 | * Base Component (FilesystemItem)::
22 | -Provides a common interface for both `File` and `Folder`.
23 | -Declares methods for getting size and rendering.
24 | * Leaf Component (File):
25 | -Represents individual files.
26 | -Implements the size calculation and rendering logic for files.
27 | * Composite Component (Folder):
28 | -Represents folders that can contain other FilesystemItem objects.
29 | -Implements logic for adding, removing, and calculating size for all children.
30 | -Combines rendering output from its children.
31 | * Concrete Implementations (PayPalGateway, StripeGateway):
32 | -Specific implementations for different payment gateways.
33 | * Client Code:
34 | -Builds a hierarchical structure of files and folders.
35 | -Works with the structure using the abstract FilesystemItem interface.
--------------------------------------------------------------------------------
/patterns/Structural/Proxy/README.md:
--------------------------------------------------------------------------------
1 | Proxy is a structural design pattern that provides an object that acts as a substitute for a real service object used by a client. A proxy receives client requests, does some work (access control, caching, etc.) and then passes the request to a service object.
2 |
3 | The proxy object has the same interface as a service, which makes it interchangeable with a real object when passed to a client.
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Bridge design pattern and focuses on the following questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## Downloader
15 | This example demonstrates how the Proxy pattern can improve the performance of a downloader object by caching its results.
16 |
17 | ## Image
18 | The Subject interface defines the common interface for both the RealSubject and the Proxy. In this example, we are simulating an online image loading service.
19 |
20 | ### Explanation:
21 | 1. **Subject Interface:**
22 | - `Image`: Defines the `display()` method that both `RealImage` and `ProxyImage` implement.
23 |
24 | 2. **RealSubject:**
25 | - `RealImage`: Represents the actual image that performs the work of loading and displaying an image.
26 |
27 | 3. **Proxy:**
28 | - `ProxyImage`: Controls access to the `RealImage`. It delays the loading process by caching the image after the first load. It checks if the image is already loaded and if so, it simply displays it.
29 |
30 | 4. **Client Code:**
31 | - The client interacts with the `Image` interface, which means it can use either `RealImage` or `ProxyImage` without knowing the difference. In the case of `ProxyImage`, it saves resources by caching the result and reusing it.
32 |
33 | This examples demonstrates the **Proxy** pattern for optimizing the loading of resources and caching. The `Proxy` provides a simplified and efficient way to manage resource-heavy operations.
34 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Mediator/README.md:
--------------------------------------------------------------------------------
1 | Mediator is a behavioral design pattern that reduces coupling between components of a program by making them communicate indirectly, through a special mediator object.
2 |
3 | The Mediator makes it easy to modify, extend and reuse individual components because they’re no longer dependent on the dozens of other classes.
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Abstract Factory design pattern. It focuses on answering these questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## TrackTriggerEvent
15 | In this example, the Mediator pattern expands the idea of the Observer pattern by providing a centralized event dispatcher. It allows any object to track & trigger events in other objects without depending on their classes.
16 |
17 | ## UserAccountManagement
18 | System that dispatches events for various user-related actions similar to the EventDispatcher example
19 |
20 | ### Explanation:
21 | - **EventDispatcher**: The Mediator component. It handles the subscription of observers (components) and broadcasts events to the relevant subscribers.
22 | - **Observer Interface**: Each component that wants to listen for events must implement this interface.
23 | - **UserRepository**: A component that manages user records, subscribing to events such as "users:created", "users:updated", and "users:deleted".
24 | - **Logger**: A concrete observer that logs event details to a file.
25 | - **OnboardingNotification**: A concrete observer that sends notifications when a user is created.
26 |
27 | ### Output:
28 | ```
29 | UserRepository: Creating a user.
30 | EventDispatcher: Broadcasting the 'users:created' event.
31 | Logger: I've written 'users:created' entry to the log.
32 | OnboardingNotification: The notification has been emailed!
33 | User: I can now delete myself without worrying about the repository.
34 | EventDispatcher: Broadcasting the 'users:deleted' event.
35 | Logger: I've written 'users:deleted' entry to the log.
36 | ```
--------------------------------------------------------------------------------
/patterns/Structural/Flyweight/README.md:
--------------------------------------------------------------------------------
1 | Flyweight is a structural design pattern that allows programs to support vast quantities of objects by keeping their memory consumption low.
2 |
3 | The pattern achieves it by sharing parts of object state between multiple objects. In other words, the Flyweight saves RAM by caching the same data used by different objects.
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Bridge design pattern and focuses on the following questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## CatsFeatures
15 | In this example, the Flyweight pattern is used to minimize the RAM usage of objects in an animal database of a cat-only veterinary clinic. Each record in the database is represented by a Cat object. Its data consists of two parts:
16 |
17 | 1. Unique (extrinsic) data such as a pet’s name, age, and owner info.
18 | 2. Shared (intrinsic) data such as breed name, color, texture, etc.
19 |
20 | The first part is stored directly inside the Cat class, which acts as a context. The second part, however, is stored separately and can be shared by multiple cats. This shareable data resides inside the CatVariation class. All cats that have similar features are linked to the same CatVariation class, instead of storing the duplicate data in each of their objects.
21 |
22 | ## ForestSimulation
23 | Tree objects in a forest simulation. This example highlights how intrinsic data (shared state like type and texture) is separated from extrinsic data (unique data like position).
24 |
25 | ### Explanation:
26 |
27 | 1. **TreeType (Flyweight)**: Stores intrinsic data like `name`, `color`, and `texture`.
28 | 2. **Tree (Context)**: Stores extrinsic data such as `x` and `y` (position).
29 | 3. **TreeFactory (Flyweight Factory)**: Manages shared `TreeType` instances to avoid redundant objects.
30 | 4. **Forest**: Acts as the client managing the collection of trees.
31 | 5. **Singleton TreeFactory**: Ensures only one instance of the factory exists.
32 |
33 |
--------------------------------------------------------------------------------
/patterns/Creational/Builder/JavaScript/Builder.js:
--------------------------------------------------------------------------------
1 | // Builder interface defines the steps to build the product.
2 | class Builder {
3 | producePartA() {}
4 | producePartB() {}
5 | producePartC() {}
6 | getProduct() {}
7 | }
8 |
9 | // ConcreteBuilder1 implements the Builder interface.
10 | class ConcreteBuilder1 extends Builder {
11 | constructor() {
12 | super();
13 | this.reset();
14 | }
15 |
16 | reset() {
17 | this.product = new Product1();
18 | }
19 |
20 | producePartA() {
21 | this.product.parts.push("PartA1");
22 | }
23 |
24 | producePartB() {
25 | this.product.parts.push("PartB1");
26 | }
27 |
28 | producePartC() {
29 | this.product.parts.push("PartC1");
30 | }
31 |
32 | getProduct() {
33 | const result = this.product;
34 | this.reset();
35 | return result;
36 | }
37 | }
38 |
39 | // Product represents the complex object being constructed.
40 | class Product1 {
41 | constructor() {
42 | this.parts = [];
43 | }
44 |
45 | listParts() {
46 | console.log(`Product parts: ${this.parts.join(", ")}\n`);
47 | }
48 | }
49 |
50 | // Director orchestrates the construction process.
51 | class Director {
52 | setBuilder(builder) {
53 | this.builder = builder;
54 | }
55 |
56 | buildMinimalViableProduct() {
57 | this.builder.producePartA();
58 | }
59 |
60 | buildFullFeaturedProduct() {
61 | this.builder.producePartA();
62 | this.builder.producePartB();
63 | this.builder.producePartC();
64 | }
65 | }
66 |
67 | // Client code
68 | function clientCode(director) {
69 | const builder = new ConcreteBuilder1();
70 | director.setBuilder(builder);
71 |
72 | console.log("Standard basic product:");
73 | director.buildMinimalViableProduct();
74 | builder.getProduct().listParts();
75 |
76 | console.log("Standard full featured product:");
77 | director.buildFullFeaturedProduct();
78 | builder.getProduct().listParts();
79 |
80 | console.log("Custom product:");
81 | builder.producePartA();
82 | builder.producePartC();
83 | builder.getProduct().listParts();
84 | }
85 |
86 | const director = new Director();
87 | clientCode(director);
--------------------------------------------------------------------------------
/patterns/Creational/Builder/Go/Builder.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | )
7 |
8 | // Builder interface defines the steps to build the product.
9 | type Builder interface {
10 | ProducePartA()
11 | ProducePartB()
12 | ProducePartC()
13 | GetProduct() *Product
14 | }
15 |
16 | // ConcreteBuilder1 implements the Builder interface.
17 | type ConcreteBuilder1 struct {
18 | product *Product
19 | }
20 |
21 | func NewConcreteBuilder1() *ConcreteBuilder1 {
22 | return &ConcreteBuilder1{product: &Product{}}
23 | }
24 |
25 | func (b *ConcreteBuilder1) Reset() {
26 | b.product = &Product{}
27 | }
28 |
29 | func (b *ConcreteBuilder1) ProducePartA() {
30 | b.product.parts = append(b.product.parts, "PartA1")
31 | }
32 |
33 | func (b *ConcreteBuilder1) ProducePartB() {
34 | b.product.parts = append(b.product.parts, "PartB1")
35 | }
36 |
37 | func (b *ConcreteBuilder1) ProducePartC() {
38 | b.product.parts = append(b.product.parts, "PartC1")
39 | }
40 |
41 | func (b *ConcreteBuilder1) GetProduct() *Product {
42 | result := b.product
43 | b.Reset()
44 | return result
45 | }
46 |
47 | // Product represents the complex object being constructed.
48 | type Product struct {
49 | parts []string
50 | }
51 |
52 | func (p *Product) ListParts() {
53 | fmt.Println("Product parts:", strings.Join(p.parts, ", "))
54 | }
55 |
56 | // Director orchestrates the construction process.
57 | type Director struct {
58 | builder Builder
59 | }
60 |
61 | func (d *Director) SetBuilder(builder Builder) {
62 | d.builder = builder
63 | }
64 |
65 | func (d *Director) BuildMinimalViableProduct() {
66 | d.builder.ProducePartA()
67 | }
68 |
69 | func (d *Director) BuildFullFeaturedProduct() {
70 | d.builder.ProducePartA()
71 | d.builder.ProducePartB()
72 | d.builder.ProducePartC()
73 | }
74 |
75 | // Client code
76 | func main() {
77 | director := &Director{}
78 | builder := NewConcreteBuilder1()
79 | director.SetBuilder(builder)
80 |
81 | fmt.Println("Standard basic product:")
82 | director.BuildMinimalViableProduct()
83 | builder.GetProduct().ListParts()
84 |
85 | fmt.Println("Standard full featured product:")
86 | director.BuildFullFeaturedProduct()
87 | builder.GetProduct().ListParts()
88 |
89 | fmt.Println("Custom product:")
90 | builder.ProducePartA()
91 | builder.ProducePartC()
92 | builder.GetProduct().ListParts()
93 | }
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/Go/RealWorldExample/SystemUIComponents.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // UIFactory - Abstract Factory for creating UI components
6 | type UIFactory interface {
7 | CreateButton() Button
8 | CreateCheckbox() Checkbox
9 | }
10 |
11 | // WindowsFactory - Concrete Factory for Windows OS
12 | type WindowsFactory struct{}
13 |
14 | func (w *WindowsFactory) CreateButton() Button {
15 | return &WindowsButton{}
16 | }
17 |
18 | func (w *WindowsFactory) CreateCheckbox() Checkbox {
19 | return &WindowsCheckbox{}
20 | }
21 |
22 | // MacFactory - Concrete Factory for Mac OS
23 | type MacFactory struct{}
24 |
25 | func (m *MacFactory) CreateButton() Button {
26 | return &MacButton{}
27 | }
28 |
29 | func (m *MacFactory) CreateCheckbox() Checkbox {
30 | return &MacCheckbox{}
31 | }
32 |
33 | // Button - Abstract product interface for buttons
34 | type Button interface {
35 | Render() string
36 | }
37 |
38 | // WindowsButton - Concrete product for Windows button
39 | type WindowsButton struct{}
40 |
41 | func (w *WindowsButton) Render() string {
42 | return "Rendering Windows button."
43 | }
44 |
45 | // MacButton - Concrete product for Mac button
46 | type MacButton struct{}
47 |
48 | func (m *MacButton) Render() string {
49 | return "Rendering Mac button."
50 | }
51 |
52 | // Checkbox - Abstract product interface for checkboxes
53 | type Checkbox interface {
54 | Toggle() string
55 | }
56 |
57 | // WindowsCheckbox - Concrete product for Windows checkbox
58 | type WindowsCheckbox struct{}
59 |
60 | func (w *WindowsCheckbox) Toggle() string {
61 | return "Toggling Windows checkbox."
62 | }
63 |
64 | // MacCheckbox - Concrete product for Mac checkbox
65 | type MacCheckbox struct{}
66 |
67 | func (m *MacCheckbox) Toggle() string {
68 | return "Toggling Mac checkbox."
69 | }
70 |
71 | // Client function to render UI components
72 | func renderUI(factory UIFactory) {
73 | button := factory.CreateButton()
74 | fmt.Println(button.Render())
75 |
76 | checkbox := factory.CreateCheckbox()
77 | fmt.Println(checkbox.Toggle())
78 | }
79 |
80 | func main() {
81 | fmt.Println("Testing Windows UI factory:")
82 | renderUI(&WindowsFactory{})
83 | fmt.Println()
84 |
85 | fmt.Println("Testing Mac UI factory:")
86 | renderUI(&MacFactory{})
87 | }
88 |
--------------------------------------------------------------------------------
/patterns/Behavioral/State/PHP/RealWorldExample/OrderProcess.php:
--------------------------------------------------------------------------------
1 | setState(new ShippedOrderState());
23 | }
24 | }
25 |
26 | /**
27 | * Concrete state: The order has been shipped.
28 | */
29 | class ShippedOrderState implements OrderState
30 | {
31 | public function handleOrder(Order $order): void
32 | {
33 | echo "Order has been shipped. Waiting for delivery.\n";
34 | // Transition to the next state
35 | $order->setState(new DeliveredOrderState());
36 | }
37 | }
38 |
39 | /**
40 | * Concrete state: The order has been delivered.
41 | */
42 | class DeliveredOrderState implements OrderState
43 | {
44 | public function handleOrder(Order $order): void
45 | {
46 | echo "Order has been delivered. Thank you for your purchase!\n";
47 | // The order is finished, no further transitions.
48 | }
49 | }
50 |
51 | /**
52 | * The Order class represents the context that maintains the current state.
53 | */
54 | class Order
55 | {
56 | private $state;
57 |
58 | public function __construct()
59 | {
60 | // Initial state is NewOrder
61 | $this->state = new NewOrderState();
62 | }
63 |
64 | public function setState(OrderState $state): void
65 | {
66 | $this->state = $state;
67 | }
68 |
69 | public function processOrder(): void
70 | {
71 | $this->state->handleOrder($this);
72 | }
73 | }
74 |
75 | /**
76 | * Client code
77 | */
78 |
79 | // Create a new order
80 | $order = new Order();
81 |
82 | // Process the order
83 | echo "Processing the order:\n";
84 | $order->processOrder(); // New state: Processing the order
85 |
86 | $order->processOrder(); // Shipped state: Order has been shipped
87 |
88 | $order->processOrder(); // Delivered state: Order has been delivered
89 |
90 |
--------------------------------------------------------------------------------
/patterns/Structural/Composite/README_fr.md:
--------------------------------------------------------------------------------
1 | Le **Composite** est un patron de conception structurel qui permet de composer des objets en structures arborescentes et de travailler avec ces structures comme s’il s’agissait d’objets individuels.
2 |
3 | Le **Composite** est devenu une solution populaire pour les problèmes nécessitant la construction d'une structure en arbre. Sa principale caractéristique est la capacité d’exécuter des méthodes de manière récursive sur l’ensemble de la structure et de cumuler les résultats.
4 |
5 | # Exemple conceptuel :
6 | Cet exemple illustre la structure du patron de conception **Composite** et se concentre sur les questions suivantes :
7 | - De quelles classes est-il composé ?
8 | - Quels rôles ces classes jouent-elles ?
9 | - De quelle manière les éléments du patron sont-ils liés ?
10 |
11 | Après avoir compris la structure du patron, il vous sera plus facile de saisir l'exemple suivant, basé sur un cas réel utilisant PHP, Go, JavaScript et Java.
12 |
13 | # Exemple réel :
14 | ## Arbre DOM HTML (**HTMLDOMTree**)
15 | L’arbre DOM HTML est un exemple typique de ce type de structure. Par exemple, les différents éléments d'entrée peuvent agir comme des feuilles, tandis que les éléments complexes comme les formulaires et les fieldsets jouent le rôle de composites.
16 |
17 | ## Système de fichiers (**FileSystem**)
18 | Cet exemple démontre la structure et la fonctionnalité d’un système de fichiers (fichiers et dossiers) en utilisant le patron **Composite**.
19 |
20 | ### Explication :
21 | 1. **Composant de base (FilesystemItem) :**
22 | - Fournit une interface commune pour les objets `File` et `Folder`.
23 | - Déclare des méthodes pour obtenir la taille et effectuer le rendu.
24 |
25 | 2. **Composant Feuille (File) :**
26 | - Représente des fichiers individuels.
27 | - Implémente la logique de calcul de taille et de rendu pour les fichiers.
28 |
29 | 3. **Composant Composite (Folder) :**
30 | - Représente les dossiers pouvant contenir d’autres objets **FilesystemItem**.
31 | - Implémente la logique d’ajout, de suppression et de calcul de taille pour tous les éléments enfants.
32 | - Combine les sorties de rendu de ses enfants.
33 |
34 | 4. **Code client :**
35 | - Construit une structure hiérarchique de fichiers et de dossiers.
36 | - Travaille avec la structure en utilisant l’interface abstraite **FilesystemItem**.
37 |
--------------------------------------------------------------------------------
/patterns/Structural/Proxy/README_fr.md:
--------------------------------------------------------------------------------
1 | **Proxy** est un patron de conception structurel qui fournit un objet servant de substitut à un véritable objet de service utilisé par un client. Un proxy reçoit les requêtes du client, effectue certaines actions (contrôle d'accès, mise en cache, etc.) puis transmet la requête à un objet de service.
2 |
3 | L'objet proxy possède la même interface qu'un service, ce qui le rend interchangeable avec un véritable objet lorsqu'il est transmis à un client.
4 |
5 | # Exemple conceptuel :
6 | Cet exemple illustre la structure du patron de conception **Bridge** et se concentre sur les questions suivantes :
7 | * De quelles classes est-il composé ?
8 | * Quels rôles ces classes jouent-elles ?
9 | * De quelle manière les éléments du patron sont-ils liés ?
10 |
11 | Après avoir appris la structure du patron, il vous sera plus facile de comprendre l'exemple suivant, basé sur un cas d'utilisation réel en PHP, Go, JS et Java.
12 |
13 | # Exemple du monde réel :
14 | ## Downloader
15 | Cet exemple montre comment le patron Proxy peut améliorer les performances d'un objet de téléchargement en mettant en cache ses résultats.
16 |
17 | ## Image
18 | L'interface **Subject** définit l'interface commune à la fois pour le **RealSubject** et le **Proxy**. Dans cet exemple, nous simulons un service de chargement d'images en ligne.
19 |
20 | ### Explication :
21 | 1. **Interface Subject :**
22 | - `Image` : Définit la méthode `display()` que les classes `RealImage` et `ProxyImage` implémentent toutes deux.
23 |
24 | 2. **RealSubject :**
25 | - `RealImage` : Représente l'image réelle qui effectue le travail de chargement et d'affichage de l'image.
26 |
27 | 3. **Proxy :**
28 | - `ProxyImage` : Contrôle l'accès à `RealImage`. Il retarde le processus de chargement en mettant en cache l'image après le premier chargement. Il vérifie si l'image est déjà chargée et, dans ce cas, l'affiche simplement.
29 |
30 | 4. **Code Client :**
31 | - Le client interagit avec l'interface `Image`, ce qui signifie qu'il peut utiliser soit `RealImage`, soit `ProxyImage` sans connaître la différence. Dans le cas de `ProxyImage`, il économise des ressources en mettant en cache le résultat et en le réutilisant.
32 |
33 | Cet exemple montre comment le patron **Proxy** peut optimiser le chargement des ressources et la mise en cache. Le **Proxy** fournit un moyen simplifié et efficace de gérer les opérations lourdes en ressources.
34 |
--------------------------------------------------------------------------------
/patterns/Structural/Facade/README.md:
--------------------------------------------------------------------------------
1 | Facade is a structural design pattern that provides a simplified (but limited) interface to a complex system of classes, library or framework.
2 |
3 | While Facade decreases the overall complexity of the application, it also helps to move unwanted dependencies to one place.
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Bridge design pattern and focuses on the following questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## SubSystem
15 | In this example, the Facade hides the complexity of the YouTube API and FFmpeg library from the client code. Instead of working with dozens of classes, the client uses a simple method on the Facade.
16 |
17 | ## MealOrder
18 | This example demonstrates how to simplify complex subsystem interactions by creating a unified interface (Facade) that provides easy access to the subsystem's functionality.
19 |
20 | ### Explanation:
21 |
22 |
23 | ### Explanation:
24 | 1. **Subsystems:**
25 | - `Restaurant` handles meal preparation.
26 | - `DeliveryService` manages meal delivery.
27 | - `PaymentProcessor` processes payments.
28 |
29 | 2. **Facade Class:**
30 | - `MealOrderFacade` provides a single method `placeOrder` to encapsulate interactions with the subsystems.
31 |
32 | 3. **Client Code:**
33 | - The client interacts only with the `MealOrderFacade`, simplifying the process of placing an order.
34 |
35 |
36 | ## HomeAutomation
37 | This example demonstrates controlling a complex home automation system through a simple interface using the Facade pattern.
38 |
39 | ### Explanation:
40 | 1. **Subsystems:**
41 | - `SmartLights` controls the lights (turn on/dim).
42 | - `Thermostat` controls the home temperature.
43 | - `SecuritySystem` manages security (activate/deactivate).
44 |
45 | 2. **Facade Class:**
46 | - `SmartHomeFacade` provides methods like `startMorningRoutine` and `startNightRoutine` that combine subsystem operations into simple routines.
47 |
48 | 3. **Client Code:**
49 | - The client calls high-level methods on the `SmartHomeFacade` instead of interacting directly with individual subsystems.
50 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/Go/RealWorldExample/DataBaseConnection.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // Abstract Factory interface for creating database connections and queries
6 | type DatabaseFactory interface {
7 | CreateConnection() Connection
8 | CreateQuery() Query
9 | }
10 |
11 | // Concrete Factory for MySQL database
12 | type MySQLFactory struct{}
13 |
14 | func (f *MySQLFactory) CreateConnection() Connection {
15 | return &MySQLConnection{}
16 | }
17 |
18 | func (f *MySQLFactory) CreateQuery() Query {
19 | return &MySQLQuery{}
20 | }
21 |
22 | // Concrete Factory for PostgreSQL database
23 | type PostgreSQLFactory struct{}
24 |
25 | func (f *PostgreSQLFactory) CreateConnection() Connection {
26 | return &PostgreSQLConnection{}
27 | }
28 |
29 | func (f *PostgreSQLFactory) CreateQuery() Query {
30 | return &PostgreSQLQuery{}
31 | }
32 |
33 | // Abstract product interface for database connections
34 | type Connection interface {
35 | Connect() string
36 | }
37 |
38 | // Concrete product for MySQL connection
39 | type MySQLConnection struct{}
40 |
41 | func (c *MySQLConnection) Connect() string {
42 | return "Connected to MySQL database."
43 | }
44 |
45 | // Concrete product for PostgreSQL connection
46 | type PostgreSQLConnection struct{}
47 |
48 | func (c *PostgreSQLConnection) Connect() string {
49 | return "Connected to PostgreSQL database."
50 | }
51 |
52 | // Abstract product interface for database queries
53 | type Query interface {
54 | Execute() string
55 | }
56 |
57 | // Concrete product for MySQL query
58 | type MySQLQuery struct{}
59 |
60 | func (q *MySQLQuery) Execute() string {
61 | return "Executing MySQL query."
62 | }
63 |
64 | // Concrete product for PostgreSQL query
65 | type PostgreSQLQuery struct{}
66 |
67 | func (q *PostgreSQLQuery) Execute() string {
68 | return "Executing PostgreSQL query."
69 | }
70 |
71 | // Client code that interacts with the abstract factory and products
72 | func clientCode(factory DatabaseFactory) {
73 | connection := factory.CreateConnection()
74 | fmt.Println(connection.Connect())
75 |
76 | query := factory.CreateQuery()
77 | fmt.Println(query.Execute())
78 | }
79 |
80 | func main() {
81 | // Testing MySQL factory
82 | fmt.Println("Testing MySQL factory:")
83 | clientCode(&MySQLFactory{})
84 | fmt.Println()
85 |
86 | // Testing PostgreSQL factory
87 | fmt.Println("Testing PostgreSQL factory:")
88 | clientCode(&PostgreSQLFactory{})
89 | }
90 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/Go/RealWorldExamples/DatabaseConnection.go:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Database Connection Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern for managing a
6 | | database connection, ensuring that only one instance of the connection
7 | | is created and used throughout the application.
8 | |--------------------------------------------------------------------------
9 | | @category Design Pattern
10 | | @package Creational/Singleton
11 | | @version 1.0.0
12 | | @license MIT License
13 | | @link https://github.com/JawherKl/design-patterns-in-php
14 | |--------------------------------------------------------------------------
15 | |
16 | | Key Components:
17 | | 1. **Singleton Class**: Implements the `getInstance` method to ensure
18 | | only one instance of the database connection is created.
19 | | 2. **Static Instance Storage**: Ensures that the same instance of the
20 | | database connection is used throughout the application.
21 | | 3. **Client Code**: Demonstrates using the Singleton to retrieve the
22 | | database connection, ensuring that only one connection instance exists.
23 | |
24 | | Use Case:
25 | | Use the Singleton pattern to manage a global database connection in an
26 | | application, ensuring that all parts of the application use the same
27 | | connection instance, optimizing resource management.
28 | */
29 |
30 | package main
31 |
32 | import (
33 | "fmt"
34 | "sync"
35 | )
36 |
37 | // DatabaseConnection Singleton
38 | type DatabaseConnection struct {
39 | connection string
40 | }
41 |
42 | var instance *DatabaseConnection
43 | var once sync.Once
44 |
45 | // GetInstance returns the single instance of DatabaseConnection
46 | func GetInstance() *DatabaseConnection {
47 | once.Do(func() {
48 | instance = &DatabaseConnection{
49 | connection: "Database Connection Established",
50 | }
51 | })
52 | return instance
53 | }
54 |
55 | // GetConnection returns the database connection
56 | func (db *DatabaseConnection) GetConnection() string {
57 | return db.connection
58 | }
59 |
60 | func main() {
61 | // Client code
62 | db1 := GetInstance()
63 | fmt.Println(db1.GetConnection())
64 |
65 | db2 := GetInstance()
66 | if db1 == db2 {
67 | fmt.Println("Only one instance of DatabaseConnection exists.")
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/JavaScript/RealWorldExamples/CacheManager.js:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Cache Manager Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern for managing a
6 | | cache system, ensuring that only one instance of the cache manager
7 | | exists and is used throughout the application.
8 | |--------------------------------------------------------------------------
9 | | @category Design Pattern
10 | | @package Creational/Singleton
11 | | @version 1.0.0
12 | | @license MIT License
13 | | @link https://github.com/JawherKl/design-patterns-in-js
14 | |--------------------------------------------------------------------------
15 | |
16 | | Key Components:
17 | | 1. **Singleton Class**: Implements the `getInstance` method to manage
18 | | the single instance of the cache manager.
19 | | 2. **Static Instance Storage**: Ensures only one instance of the cache
20 | | manager is created.
21 | | 3. **Client Code**: Demonstrates caching data using the singleton cache
22 | | manager instance.
23 | |
24 | | Use Case:
25 | | Use the Singleton pattern to manage a global cache system, ensuring that
26 | | all parts of the application access and modify the cache through the
27 | | same instance, optimizing memory and performance.
28 | */
29 |
30 | class CacheManager {
31 | static instance;
32 |
33 | constructor() {
34 | if (CacheManager.instance) {
35 | throw new Error("CacheManager is a singleton and cannot be instantiated directly.");
36 | }
37 | this.cache = {};
38 | CacheManager.instance = this;
39 | }
40 |
41 | // Accessor for the singleton instance
42 | static getInstance() {
43 | if (!CacheManager.instance) {
44 | new CacheManager(); // Initialize the instance
45 | }
46 | return CacheManager.instance;
47 | }
48 |
49 | // Set cache value
50 | set(key, value) {
51 | this.cache[key] = value;
52 | }
53 |
54 | // Get cache value
55 | get(key) {
56 | return this.cache[key] || null;
57 | }
58 | }
59 |
60 | // Client code
61 | const cache = CacheManager.getInstance();
62 | cache.set('user_1', { name: 'John Doe', email: 'john@example.com' });
63 |
64 | const user = cache.get('user_1');
65 | console.log("Cached User:", JSON.stringify(user));
66 |
--------------------------------------------------------------------------------
/patterns/Structural/Decorator/README_fr.md:
--------------------------------------------------------------------------------
1 | Le **Decorator** est un patron de conception structurel qui permet d’ajouter dynamiquement de nouveaux comportements à des objets en les enveloppant dans des objets spéciaux (wrappers) qui contiennent ces comportements.
2 |
3 | Porter des vêtements est un exemple d’utilisation des **decorators**. Quand il fait froid, vous mettez un pull. Si vous avez encore froid, vous ajoutez une veste. S’il pleut, vous enfilez un imperméable. Tous ces vêtements "étendent" votre comportement de base sans faire partie intégrante de vous, et vous pouvez les enlever facilement lorsque vous n'en avez plus besoin.
4 |
5 | # Exemple conceptuel :
6 | Cet exemple illustre la structure du patron de conception **Decorator** et se concentre sur les questions suivantes :
7 | - De quelles classes est-il composé ?
8 | - Quels rôles ces classes jouent-elles ?
9 | - De quelle manière les éléments du patron sont-ils liés ?
10 |
11 | Après avoir compris la structure du patron, il vous sera plus facile de saisir l'exemple suivant, basé sur un cas réel utilisant PHP, Go, JavaScript et Java.
12 |
13 | # Exemple réel :
14 | ## Filtrage de texte (**TextFiltering**)
15 | Dans cet exemple, le patron **Decorator** aide à construire des règles complexes de filtrage de texte pour nettoyer le contenu avant de l’afficher sur une page web. Différents types de contenu, comme les commentaires, les messages de forum ou les messages privés, nécessitent des ensembles de filtres différents.
16 |
17 | ## Transformation de message (**MessageTransformation**)
18 | Dans ce cas, nous allons décorer une classe de base **Message** pour ajouter diverses transformations de texte comme le chiffrement, l'inversion et la mise en majuscules.
19 |
20 | ### Explication :
21 | 1. **Interface Composant (Message) :**
22 | - Déclare la méthode `getText()` pour traiter le texte.
23 |
24 | 2. **Composant Concret (SimpleMessage) :**
25 | - Implémente l’interface pour retourner le message original.
26 |
27 | 3. **Décorateur de base (MessageDecorator) :**
28 | - Implémente la même interface et maintient une référence à un objet **Message**.
29 |
30 | 4. **Décorateurs Concrets :**
31 | - `ReverseTextDecorator` : Inverse le texte.
32 | - `UppercaseDecorator` : Convertit le texte en majuscules.
33 | - `EncryptionDecorator` : Applique un chiffrement ROT13.
34 |
35 | 5. **Code client :**
36 | - Démontre la composition dynamique des **decorators** pour modifier le message.
37 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/JavaScript/Singleton.js:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Implementation Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern, which ensures a
6 | | class has only one instance and provides a global point of access to it.
7 | |--------------------------------------------------------------------------
8 | | @category Design Pattern
9 | | @package Creational/Singleton
10 | | @version 1.0.0
11 | | @license MIT License
12 | | @link https://github.com/JawherKl/design-patterns-in-js
13 | |--------------------------------------------------------------------------
14 | |
15 | | Key Components:
16 | | 1. **Singleton Class**: Implements the `getInstance` method for managing
17 | | the single instance.
18 | | 2. **Static Instance Storage**: Ensures only one instance per subclass.
19 | | 3. **Client Code**: Demonstrates that the same instance is returned.
20 | |
21 | | Use Case:
22 | | Use the Singleton pattern when only one instance of a class should exist,
23 | | such as in managing database connections or configuration settings.
24 | */
25 |
26 | class Singleton {
27 | // Static field to store the instance of the Singleton
28 | static instances = {};
29 |
30 | // Private constructor to prevent direct instantiation
31 | constructor() {
32 | if (Singleton.instances[this.constructor.name]) {
33 | throw new Error("Cannot instantiate Singleton class directly.");
34 | }
35 | }
36 |
37 | // Static method to get the instance of the Singleton
38 | static getInstance() {
39 | const className = this.name;
40 |
41 | if (!Singleton.instances[className]) {
42 | Singleton.instances[className] = new this();
43 | }
44 |
45 | return Singleton.instances[className];
46 | }
47 |
48 | // Singleton class business logic can be implemented here
49 | someBusinessLogic() {
50 | // ...
51 | }
52 | }
53 |
54 | // Client code
55 | function clientCode() {
56 | const s1 = Singleton.getInstance();
57 | const s2 = Singleton.getInstance();
58 |
59 | if (s1 === s2) {
60 | console.log("Singleton works, both variables contain the same instance.");
61 | } else {
62 | console.log("Singleton failed, variables contain different instances.");
63 | }
64 | }
65 |
66 | clientCode();
67 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/Go/RealWorldExamples/CacheManager.go:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Cache Manager Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern for managing a
6 | | cache system, ensuring that only one instance of the cache manager
7 | | exists and is used throughout the application.
8 | |--------------------------------------------------------------------------
9 | | @category Design Pattern
10 | | @package Creational/Singleton
11 | | @version 1.0.0
12 | | @license MIT License
13 | | @link https://github.com/JawherKl/design-patterns-in-php
14 | |--------------------------------------------------------------------------
15 | |
16 | | Key Components:
17 | | 1. **Singleton Class**: Implements the `getInstance` method to manage
18 | | the single instance of the cache manager.
19 | | 2. **Static Instance Storage**: Ensures only one instance of the cache
20 | | manager is created.
21 | | 3. **Client Code**: Demonstrates caching data using the singleton cache
22 | | manager instance.
23 | |
24 | | Use Case:
25 | | Use the Singleton pattern to manage a global cache system, ensuring that
26 | | all parts of the application access and modify the cache through the
27 | | same instance, optimizing memory and performance.
28 | */
29 |
30 | package main
31 |
32 | import (
33 | "fmt"
34 | "sync"
35 | )
36 |
37 | // CacheManager Singleton
38 | type CacheManager struct {
39 | cache map[string]interface{}
40 | mu sync.RWMutex
41 | }
42 |
43 | var instance *CacheManager
44 | var once sync.Once
45 |
46 | // GetInstance returns the single instance of CacheManager
47 | func GetInstance() *CacheManager {
48 | once.Do(func() {
49 | instance = &CacheManager{
50 | cache: make(map[string]interface{}),
51 | }
52 | })
53 | return instance
54 | }
55 |
56 | // Set adds a value to the cache
57 | func (c *CacheManager) Set(key string, value interface{}) {
58 | c.mu.Lock()
59 | defer c.mu.Unlock()
60 | c.cache[key] = value
61 | }
62 |
63 | // Get retrieves a value from the cache
64 | func (c *CacheManager) Get(key string) interface{} {
65 | c.mu.RLock()
66 | defer c.mu.RUnlock()
67 | return c.cache[key]
68 | }
69 |
70 | func main() {
71 | // Client code
72 | cache := GetInstance()
73 | cache.Set("user_1", map[string]string{"name": "John Doe", "email": "john@example.com"})
74 |
75 | user := cache.Get("user_1")
76 | fmt.Printf("Cached User: %v\n", user)
77 | }
78 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/Go/RealWorldExamples/ApplicationSettings.go:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Application Settings Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern for managing
6 | | application settings, ensuring that only one instance of the settings
7 | | is created and accessed globally.
8 | |--------------------------------------------------------------------------
9 | | @category Design Pattern
10 | | @package Creational/Singleton
11 | | @version 1.0.0
12 | | @license MIT License
13 | | @link https://github.com/JawherKl/design-patterns-in-go
14 | |--------------------------------------------------------------------------
15 | |
16 | | Key Components:
17 | | 1. **Singleton Class**: Implements the `getInstance` method to manage
18 | | the single instance of the settings.
19 | | 2. **Static Instance Storage**: Ensures only one instance of the class
20 | | is created.
21 | | 3. **Client Code**: Demonstrates accessing and modifying the singleton
22 | | instance to manage application settings.
23 | |
24 | | Use Case:
25 | | Use the Singleton pattern to manage a global instance that holds
26 | | application-wide settings, ensuring that all parts of the application
27 | | work with the same configuration.
28 | */
29 |
30 | package main
31 |
32 | import (
33 | "fmt"
34 | "sync"
35 | )
36 |
37 | type AppSettings struct {
38 | settings map[string]string
39 | }
40 |
41 | var instance *AppSettings
42 | var mu sync.Mutex
43 |
44 | // GetInstance ensures that only one instance of the AppSettings class is created
45 | func GetInstance() *AppSettings {
46 | mu.Lock()
47 | defer mu.Unlock()
48 |
49 | if instance == nil {
50 | instance = &AppSettings{
51 | settings: map[string]string{
52 | "appName": "My Application",
53 | "version": "1.0.0",
54 | },
55 | }
56 | }
57 | return instance
58 | }
59 |
60 | // GetSetting retrieves the setting by key
61 | func (a *AppSettings) GetSetting(key string) string {
62 | return a.settings[key]
63 | }
64 |
65 | // SetSetting sets a value for a given setting key
66 | func (a *AppSettings) SetSetting(key, value string) {
67 | a.settings[key] = value
68 | }
69 |
70 | func main() {
71 | // Client code
72 | appSettings := GetInstance()
73 | fmt.Println("App Name:", appSettings.GetSetting("appName"))
74 |
75 | appSettings.SetSetting("version", "1.0.1")
76 | fmt.Println("Updated Version:", appSettings.GetSetting("version"))
77 | }
78 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/JavaScript/RealWorldExamples/DatabaseConnection.js:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Database Connection Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern for managing a
6 | | database connection, ensuring that only one instance of the connection
7 | | is created and used throughout the application.
8 | |--------------------------------------------------------------------------
9 | | @category Design Pattern
10 | | @package Creational/Singleton
11 | | @version 1.0.0
12 | | @license MIT License
13 | | @link https://github.com/JawherKl/design-patterns-in-js
14 | |--------------------------------------------------------------------------
15 | |
16 | | Key Components:
17 | | 1. **Singleton Class**: Implements the `getInstance` method to ensure
18 | | only one instance of the database connection is created.
19 | | 2. **Static Instance Storage**: Ensures that the same instance of the
20 | | database connection is used throughout the application.
21 | | 3. **Client Code**: Demonstrates using the Singleton to retrieve the
22 | | database connection, ensuring that only one connection instance exists.
23 | |
24 | | Use Case:
25 | | Use the Singleton pattern to manage a global database connection in an
26 | | application, ensuring that all parts of the application use the same
27 | | connection instance, optimizing resource management.
28 | */
29 |
30 | class DatabaseConnection {
31 | static instance;
32 |
33 | constructor() {
34 | if (DatabaseConnection.instance) {
35 | throw new Error("DatabaseConnection is a singleton and cannot be instantiated directly.");
36 | }
37 | this.connection = "Database Connection Established";
38 | DatabaseConnection.instance = this;
39 | }
40 |
41 | // Accessor for the singleton instance
42 | static getInstance() {
43 | if (!DatabaseConnection.instance) {
44 | new DatabaseConnection(); // Initialize the instance
45 | }
46 | return DatabaseConnection.instance;
47 | }
48 |
49 | // Get the connection
50 | getConnection() {
51 | return this.connection;
52 | }
53 | }
54 |
55 | // Client code
56 | const db1 = DatabaseConnection.getInstance();
57 | console.log(db1.getConnection());
58 |
59 | const db2 = DatabaseConnection.getInstance();
60 | if (db1 === db2) {
61 | console.log("Only one instance of DatabaseConnection exists.");
62 | }
63 |
--------------------------------------------------------------------------------
/patterns/Structural/Proxy/PHP/RealWorldExample/Image.php:
--------------------------------------------------------------------------------
1 | fileName = $fileName;
26 | }
27 |
28 | public function display(): void
29 | {
30 | echo "Displaying image: " . $this->fileName . "\n";
31 | }
32 | }
33 |
34 | /**
35 | * The Proxy class is used to delay the loading of the real image. It performs
36 | * a check to determine if the image has already been loaded, and if not,
37 | * it fetches it. If the image has already been loaded, it will simply display
38 | * it without calling the RealSubject.
39 | */
40 | class ProxyImage implements Image
41 | {
42 | private $realImage;
43 | private $fileName;
44 |
45 | public function __construct(string $fileName)
46 | {
47 | $this->fileName = $fileName;
48 | }
49 |
50 | public function display(): void
51 | {
52 | // Only load the real image if it has not been loaded before
53 | if ($this->realImage === null) {
54 | echo "Loading image: " . $this->fileName . "\n";
55 | $this->realImage = new RealImage($this->fileName);
56 | }
57 | $this->realImage->display();
58 | }
59 | }
60 |
61 | /**
62 | * The client code interacts with the Proxy object, which internally manages
63 | * the loading and displaying of the image. The client doesn't need to know
64 | * if the image is already loaded or not.
65 | */
66 | function clientCode(Image $image)
67 | {
68 | $image->display(); // Image will be loaded and displayed
69 | $image->display(); // Image will be displayed from cache
70 | }
71 |
72 | // Client code with RealImage
73 | echo "Executing client code with RealSubject:\n";
74 | $realImage = new RealImage("photo.jpg");
75 | clientCode($realImage);
76 |
77 | echo "\n";
78 |
79 | // Client code with ProxyImage
80 | echo "Executing client code with Proxy:\n";
81 | $proxyImage = new ProxyImage("photo.jpg");
82 | clientCode($proxyImage);
83 |
84 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/JavaScript/RealWorldExample/SystemUIComponents.js:
--------------------------------------------------------------------------------
1 | // UIFactory.js - Abstract Factory for creating UI components
2 | class UIFactory {
3 | createButton() {
4 | throw new Error("Method 'createButton()' must be implemented.");
5 | }
6 |
7 | createCheckbox() {
8 | throw new Error("Method 'createCheckbox()' must be implemented.");
9 | }
10 | }
11 |
12 | // WindowsFactory.js - Concrete Factory for Windows OS
13 | class WindowsFactory extends UIFactory {
14 | createButton() {
15 | return new WindowsButton();
16 | }
17 |
18 | createCheckbox() {
19 | return new WindowsCheckbox();
20 | }
21 | }
22 |
23 | // MacFactory.js - Concrete Factory for Mac OS
24 | class MacFactory extends UIFactory {
25 | createButton() {
26 | return new MacButton();
27 | }
28 |
29 | createCheckbox() {
30 | return new MacCheckbox();
31 | }
32 | }
33 |
34 | // Button.js - Abstract product interface for buttons
35 | class Button {
36 | render() {
37 | throw new Error("Method 'render()' must be implemented.");
38 | }
39 | }
40 |
41 | // WindowsButton.js - Concrete product for Windows button
42 | class WindowsButton extends Button {
43 | render() {
44 | return "Rendering Windows button.";
45 | }
46 | }
47 |
48 | // MacButton.js - Concrete product for Mac button
49 | class MacButton extends Button {
50 | render() {
51 | return "Rendering Mac button.";
52 | }
53 | }
54 |
55 | // Checkbox.js - Abstract product interface for checkboxes
56 | class Checkbox {
57 | toggle() {
58 | throw new Error("Method 'toggle()' must be implemented.");
59 | }
60 | }
61 |
62 | // WindowsCheckbox.js - Concrete product for Windows checkbox
63 | class WindowsCheckbox extends Checkbox {
64 | toggle() {
65 | return "Toggling Windows checkbox.";
66 | }
67 | }
68 |
69 | // MacCheckbox.js - Concrete product for Mac checkbox
70 | class MacCheckbox extends Checkbox {
71 | toggle() {
72 | return "Toggling Mac checkbox.";
73 | }
74 | }
75 |
76 | // Client.js - Client code
77 | function renderUI(factory) {
78 | const button = factory.createButton();
79 | console.log(button.render());
80 |
81 | const checkbox = factory.createCheckbox();
82 | console.log(checkbox.toggle());
83 | }
84 |
85 | // Usage
86 | console.log("Testing Windows UI factory:");
87 | renderUI(new WindowsFactory());
88 | console.log("\n");
89 |
90 | console.log("Testing Mac UI factory:");
91 | renderUI(new MacFactory());
92 |
--------------------------------------------------------------------------------
/patterns/Creational/Builder/README.md:
--------------------------------------------------------------------------------
1 | Builder is a creational design pattern, which allows constructing complex objects step by step.
2 |
3 | Unlike other creational patterns, Builder doesn’t require products to have a common interface. That makes it possible to produce different products using the same construction process.
4 |
5 | # Conceptual Example
6 | This example illustrates the structure of the Builder design pattern and focuses on the following questions:
7 |
8 | * What classes does it consist of?
9 | * What roles do these classes play?
10 | * In what way the elements of the pattern are related?
11 |
12 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
13 |
14 | # Real World Example:
15 | ## SQL Query Builder:
16 | The builder interface defines the common steps required to build a generic SQL query. On the other hand, concrete builders, corresponding to different SQL dialects, implement these steps by returning parts of SQL queries that can be executed in a particular database engine.
17 |
18 | ## Meal Plan:
19 | The idea is to have a flexible builder that can create either a vegetarian meal plan or a standard meal plan by combining various components like main course, side dish, and dessert.
20 |
21 | ### Explanation:
22 | * MealPlan: The complex object we are building.
23 | * MealPlanBuilder: An interface defining the steps to create a meal.
24 | * StandardMealPlanBuilder and VegetarianMealPlanBuilder: Concrete builders that follow the interface to assemble different meal plans.
25 | * MealPlanDirector: A director class that encapsulates the construction logic, ensuring the builder methods are called in the correct sequence.
26 |
27 | This example demonstrates how the Builder pattern can be used to create different meal plans with a common construction process. You can add more customization (e.g., drinks or appetizers) by extending the builder interface.
28 |
29 | ## Computer Assembly
30 | ### Explanation:
31 | * Builder Interface (ComputerBuilder): Declares methods to set computer components.
32 | * Concrete Builders (GamingComputerBuilder, OfficeComputerBuilder): Assemble computers with specific configurations (gaming or office).
33 | * Product Class (Computer): Represents the computer and holds its parts.
34 | * Director (Director): Guides the assembly process by deciding how to configure the computer (gaming or office).
35 | * Client Code: Calls the director to create different types of computers.
36 |
37 | This shows how the Builder pattern is useful when creating complex objects step-by-step, with various configurations.
38 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/JavaScript/RealWorldExample/DataBaseConnection.js:
--------------------------------------------------------------------------------
1 | // AbstractFactory.js - DatabaseFactory Interface
2 | class DatabaseFactory {
3 | createConnection() {
4 | throw new Error("Method 'createConnection()' must be implemented.");
5 | }
6 |
7 | createQuery() {
8 | throw new Error("Method 'createQuery()' must be implemented.");
9 | }
10 | }
11 |
12 | // MySQLFactory.js - Concrete Factory for MySQL
13 | class MySQLFactory extends DatabaseFactory {
14 | createConnection() {
15 | return new MySQLConnection();
16 | }
17 |
18 | createQuery() {
19 | return new MySQLQuery();
20 | }
21 | }
22 |
23 | // PostgreSQLFactory.js - Concrete Factory for PostgreSQL
24 | class PostgreSQLFactory extends DatabaseFactory {
25 | createConnection() {
26 | return new PostgreSQLConnection();
27 | }
28 |
29 | createQuery() {
30 | return new PostgreSQLQuery();
31 | }
32 | }
33 |
34 | // Connection.js - Connection Interface
35 | class Connection {
36 | connect() {
37 | throw new Error("Method 'connect()' must be implemented.");
38 | }
39 | }
40 |
41 | // MySQLConnection.js - Concrete MySQL Connection
42 | class MySQLConnection extends Connection {
43 | connect() {
44 | return "Connected to MySQL database.";
45 | }
46 | }
47 |
48 | // PostgreSQLConnection.js - Concrete PostgreSQL Connection
49 | class PostgreSQLConnection extends Connection {
50 | connect() {
51 | return "Connected to PostgreSQL database.";
52 | }
53 | }
54 |
55 | // Query.js - Query Interface
56 | class Query {
57 | execute() {
58 | throw new Error("Method 'execute()' must be implemented.");
59 | }
60 | }
61 |
62 | // MySQLQuery.js - Concrete MySQL Query
63 | class MySQLQuery extends Query {
64 | execute() {
65 | return "Executing MySQL query.";
66 | }
67 | }
68 |
69 | // PostgreSQLQuery.js - Concrete PostgreSQL Query
70 | class PostgreSQLQuery extends Query {
71 | execute() {
72 | return "Executing PostgreSQL query.";
73 | }
74 | }
75 |
76 | // Client.js - Client Code
77 | function clientCode(factory) {
78 | const connection = factory.createConnection();
79 | console.log(connection.connect());
80 |
81 | const query = factory.createQuery();
82 | console.log(query.execute());
83 | }
84 |
85 | // Usage
86 | console.log("Testing MySQL factory:");
87 | clientCode(new MySQLFactory());
88 | console.log("\n");
89 |
90 | console.log("Testing PostgreSQL factory:");
91 | clientCode(new PostgreSQLFactory());
92 |
--------------------------------------------------------------------------------
/patterns/Creational/Singleton/JavaScript/RealWorldExamples/ApplicationSettings.js:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Singleton Design Pattern - Application Settings Example
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Singleton Design Pattern for managing
6 | | application settings, ensuring that only one instance of the settings
7 | | is created and accessed globally.
8 | |--------------------------------------------------------------------------
9 | | @category Design Pattern
10 | | @package Creational/Singleton
11 | | @version 1.0.0
12 | | @license MIT License
13 | | @link https://github.com/JawherKl/design-patterns-in-js
14 | |--------------------------------------------------------------------------
15 | |
16 | | Key Components:
17 | | 1. **Singleton Class**: Implements the `getInstance` method to manage
18 | | the single instance of the settings.
19 | | 2. **Static Instance Storage**: Ensures only one instance of the class
20 | | is created.
21 | | 3. **Client Code**: Demonstrates accessing and modifying the singleton
22 | | instance to manage application settings.
23 | |
24 | | Use Case:
25 | | Use the Singleton pattern to manage a global instance that holds
26 | | application-wide settings, ensuring that all parts of the application
27 | | work with the same configuration.
28 | */
29 |
30 | class AppSettings {
31 | static instance;
32 |
33 | constructor() {
34 | if (AppSettings.instance) {
35 | throw new Error("AppSettings is a singleton and cannot be instantiated directly.");
36 | }
37 | // Initialize default settings
38 | this.settings = {
39 | appName: "My Application",
40 | version: "1.0.0"
41 | };
42 | AppSettings.instance = this;
43 | }
44 |
45 | // Accessor for the singleton instance
46 | static getInstance() {
47 | if (!AppSettings.instance) {
48 | new AppSettings(); // Initialize the instance
49 | }
50 | return AppSettings.instance;
51 | }
52 |
53 | // Get setting by key
54 | getSetting(key) {
55 | return this.settings[key] || null;
56 | }
57 |
58 | // Set setting by key
59 | setSetting(key, value) {
60 | this.settings[key] = value;
61 | }
62 | }
63 |
64 | // Client code
65 | const appSettings = AppSettings.getInstance();
66 | console.log("App Name: " + appSettings.getSetting("appName"));
67 |
68 | appSettings.setSetting("version", "1.0.1");
69 | console.log("Updated Version: " + appSettings.getSetting("version"));
70 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/Go/RealWorldExample/NotificationServices.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // NotificationFactory - Abstract Factory for creating notification services
6 | type NotificationFactory interface {
7 | CreateEmailService() EmailService
8 | CreateSMSService() SMSService
9 | }
10 |
11 | // GmailFactory - Concrete Factory for Gmail notification services
12 | type GmailFactory struct{}
13 |
14 | func (g *GmailFactory) CreateEmailService() EmailService {
15 | return &GmailEmailService{}
16 | }
17 |
18 | func (g *GmailFactory) CreateSMSService() SMSService {
19 | return &GmailSMSService{}
20 | }
21 |
22 | // YahooFactory - Concrete Factory for Yahoo notification services
23 | type YahooFactory struct{}
24 |
25 | func (y *YahooFactory) CreateEmailService() EmailService {
26 | return &YahooEmailService{}
27 | }
28 |
29 | func (y *YahooFactory) CreateSMSService() SMSService {
30 | return &YahooSMSService{}
31 | }
32 |
33 | // EmailService - Abstract product interface for email services
34 | type EmailService interface {
35 | SendEmail() string
36 | }
37 |
38 | // GmailEmailService - Concrete product for Gmail email service
39 | type GmailEmailService struct{}
40 |
41 | func (g *GmailEmailService) SendEmail() string {
42 | return "Sending email via Gmail."
43 | }
44 |
45 | // YahooEmailService - Concrete product for Yahoo email service
46 | type YahooEmailService struct{}
47 |
48 | func (y *YahooEmailService) SendEmail() string {
49 | return "Sending email via Yahoo."
50 | }
51 |
52 | // SMSService - Abstract product interface for SMS services
53 | type SMSService interface {
54 | SendSMS() string
55 | }
56 |
57 | // GmailSMSService - Concrete product for Gmail SMS service
58 | type GmailSMSService struct{}
59 |
60 | func (g *GmailSMSService) SendSMS() string {
61 | return "Sending SMS via Gmail."
62 | }
63 |
64 | // YahooSMSService - Concrete product for Yahoo SMS service
65 | type YahooSMSService struct{}
66 |
67 | func (y *YahooSMSService) SendSMS() string {
68 | return "Sending SMS via Yahoo."
69 | }
70 |
71 | // Client function to send notifications
72 | func sendNotifications(factory NotificationFactory) {
73 | emailService := factory.CreateEmailService()
74 | fmt.Println(emailService.SendEmail())
75 |
76 | smsService := factory.CreateSMSService()
77 | fmt.Println(smsService.SendSMS())
78 | }
79 |
80 | func main() {
81 | fmt.Println("Testing Gmail notification factory:")
82 | sendNotifications(&GmailFactory{})
83 | fmt.Println()
84 |
85 | fmt.Println("Testing Yahoo notification factory:")
86 | sendNotifications(&YahooFactory{})
87 | }
88 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/Java/RealWorldExample/ClientSystemUIComponents.java:
--------------------------------------------------------------------------------
1 | package patterns.Creational.AbstractFactory.Java.RealWorldExample;
2 |
3 | // Abstract Factory for creating UI components
4 | interface UIFactory {
5 | Button createButton();
6 | Checkbox createCheckbox();
7 | }
8 |
9 | // Concrete Factory for Windows OS
10 | class WindowsFactory implements UIFactory {
11 | @Override
12 | public Button createButton() {
13 | return new WindowsButton();
14 | }
15 |
16 | @Override
17 | public Checkbox createCheckbox() {
18 | return new WindowsCheckbox();
19 | }
20 | }
21 |
22 | // Concrete Factory for Mac OS
23 | class MacFactory implements UIFactory {
24 | @Override
25 | public Button createButton() {
26 | return new MacButton();
27 | }
28 |
29 | @Override
30 | public Checkbox createCheckbox() {
31 | return new MacCheckbox();
32 | }
33 | }
34 |
35 | // Abstract product interface for buttons
36 | interface Button {
37 | String render();
38 | }
39 |
40 | // Concrete product for Windows button
41 | class WindowsButton implements Button {
42 | @Override
43 | public String render() {
44 | return "Rendering Windows button.";
45 | }
46 | }
47 |
48 | // Concrete product for Mac button
49 | class MacButton implements Button {
50 | @Override
51 | public String render() {
52 | return "Rendering Mac button.";
53 | }
54 | }
55 |
56 | // Abstract product interface for checkboxes
57 | interface Checkbox {
58 | String toggle();
59 | }
60 |
61 | // Concrete product for Windows checkbox
62 | class WindowsCheckbox implements Checkbox {
63 | @Override
64 | public String toggle() {
65 | return "Toggling Windows checkbox.";
66 | }
67 | }
68 |
69 | // Concrete product for Mac checkbox
70 | class MacCheckbox implements Checkbox {
71 | @Override
72 | public String toggle() {
73 | return "Toggling Mac checkbox.";
74 | }
75 | }
76 |
77 | // Client code
78 | public class ClientSystemUIComponents {
79 | public static void renderUI(UIFactory factory) {
80 | Button button = factory.createButton();
81 | System.out.println(button.render());
82 |
83 | Checkbox checkbox = factory.createCheckbox();
84 | System.out.println(checkbox.toggle());
85 | }
86 |
87 | public static void main(String[] args) {
88 | System.out.println("Testing Windows UI factory:");
89 | renderUI(new WindowsFactory());
90 | System.out.println();
91 |
92 | System.out.println("Testing Mac UI factory:");
93 | renderUI(new MacFactory());
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/patterns/Structural/Flyweight/README_fr.md:
--------------------------------------------------------------------------------
1 | **Flyweight** est un patron de conception structurel qui permet aux programmes de supporter une grande quantité d'objets en gardant leur consommation mémoire faible.
2 |
3 | Le patron y parvient en partageant des parties de l'état des objets entre plusieurs objets. En d'autres termes, le Flyweight économise de la RAM en mettant en cache les mêmes données utilisées par différents objets.
4 |
5 | # Exemple conceptuel :
6 | Cet exemple illustre la structure du patron de conception Bridge et se concentre sur les questions suivantes :
7 | * De quelles classes est-il composé ?
8 | * Quels rôles ces classes jouent-elles ?
9 | * De quelle manière les éléments du patron sont-ils liés ?
10 |
11 | Après avoir appris la structure du patron, il vous sera plus facile de comprendre l'exemple suivant, basé sur un cas d'utilisation réel en PHP, Go, JS et Java.
12 |
13 | # Exemple du monde réel :
14 | ## CatsFeatures
15 | Dans cet exemple, le patron Flyweight est utilisé pour minimiser l'utilisation de la RAM des objets dans une base de données animale d'une clinique vétérinaire exclusivement pour les chats. Chaque enregistrement dans la base de données est représenté par un objet `Cat`. Ses données sont composées de deux parties :
16 |
17 | 1. Des données uniques (extrinsèques) telles que le nom de l'animal, l'âge, et les informations sur le propriétaire.
18 | 2. Des données partagées (intrinsèques) telles que le nom de la race, la couleur, la texture, etc.
19 |
20 | La première partie est stockée directement dans la classe `Cat`, qui agit comme un contexte. La deuxième partie, en revanche, est stockée séparément et peut être partagée par plusieurs chats. Ces données partagées se trouvent dans la classe `CatVariation`. Tous les chats ayant des caractéristiques similaires sont liés à la même classe `CatVariation`, au lieu de stocker les données en double dans chacun de leurs objets.
21 |
22 | ## ForestSimulation
23 | Des objets `Tree` dans une simulation de forêt. Cet exemple met en évidence la façon dont les données intrinsèques (état partagé comme le type et la texture) sont séparées des données extrinsèques (données uniques comme la position).
24 |
25 | ### Explication :
26 |
27 | 1. **TreeType (Flyweight)** : Stocke les données intrinsèques comme `nom`, `couleur`, et `texture`.
28 | 2. **Tree (Contexte)** : Stocke les données extrinsèques telles que `x` et `y` (position).
29 | 3. **TreeFactory (Flyweight Factory)** : Gère les instances partagées de `TreeType` pour éviter les objets redondants.
30 | 4. **Forest** : Agit comme le client qui gère la collection d'arbres.
31 | 5. **Singleton TreeFactory** : Garantit qu'il n'existe qu'une seule instance de la fabrique.
32 |
--------------------------------------------------------------------------------
/patterns/Structural/Facade/README_fr.md:
--------------------------------------------------------------------------------
1 | Le **Facade** est un patron de conception structurel qui fournit une interface simplifiée (mais limitée) à un système complexe de classes, de bibliothèques ou de frameworks.
2 |
3 | Bien que le **Facade** réduise la complexité globale de l'application, il aide également à regrouper les dépendances indésirables en un seul endroit.
4 |
5 | # Exemple conceptuel :
6 | Cet exemple illustre la structure du patron de conception **Facade** et se concentre sur les questions suivantes :
7 | - De quelles classes est-il composé ?
8 | - Quels rôles ces classes jouent-elles ?
9 | - De quelle manière les éléments du patron sont-ils liés ?
10 |
11 | Après avoir compris la structure du patron, il vous sera plus facile de saisir l'exemple suivant, basé sur un cas réel utilisant PHP, Go, JavaScript et Java.
12 |
13 | # Exemple réel :
14 | ## Sous-système
15 | Dans cet exemple, le **Facade** masque la complexité de l'API YouTube et de la bibliothèque FFmpeg par rapport au code client. Au lieu de manipuler des dizaines de classes, le client utilise une méthode simple sur le **Facade**.
16 |
17 | ## Commande de repas (**MealOrder**)
18 | Cet exemple démontre comment simplifier les interactions avec un sous-système complexe en créant une interface unifiée (**Facade**) qui permet un accès facile aux fonctionnalités du sous-système.
19 |
20 | ### Explication :
21 | 1. **Sous-systèmes :**
22 | - `Restaurant` gère la préparation des repas.
23 | - `DeliveryService` s'occupe de la livraison des repas.
24 | - `PaymentProcessor` traite les paiements.
25 |
26 | 2. **Classe Facade :**
27 | - `MealOrderFacade` fournit une méthode unique `placeOrder` pour encapsuler les interactions avec les sous-systèmes.
28 |
29 | 3. **Code client :**
30 | - Le client interagit uniquement avec `MealOrderFacade`, simplifiant ainsi le processus de commande.
31 |
32 | ## Domotique (**HomeAutomation**)
33 | Cet exemple démontre comment contrôler un système de domotique complexe via une interface simple en utilisant le patron **Facade**.
34 |
35 | ### Explication :
36 | 1. **Sous-systèmes :**
37 | - `SmartLights` contrôle les lumières (allumer/atténuer).
38 | - `Thermostat` régule la température de la maison.
39 | - `SecuritySystem` gère la sécurité (activer/désactiver).
40 |
41 | 2. **Classe Facade :**
42 | - `SmartHomeFacade` fournit des méthodes telles que `startMorningRoutine` et `startNightRoutine` qui combinent les opérations des sous-systèmes en routines simples.
43 |
44 | 3. **Code client :**
45 | - Le client appelle des méthodes de haut niveau sur `SmartHomeFacade` au lieu d'interagir directement avec les sous-systèmes individuels.
--------------------------------------------------------------------------------
/patterns/Creational/FactoryMethod/README.md:
--------------------------------------------------------------------------------
1 | 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.
2 |
3 | # Conceptual Example:
4 | This example illustrates the structure of the Factory Method design pattern and focuses on the following questions:
5 |
6 | * What classes does it consist of?
7 | * What roles do these classes play?
8 | * In what way the elements of the pattern are related?
9 |
10 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
11 |
12 | # Real World Example:
13 | ## Social Network:
14 | In this example, the Factory Method pattern provides an interface for creating social network connectors, which can be used to log in to the network, create posts and potentially perform other activities—and all of this without coupling the client code to specific classes of the particular social network.
15 |
16 | ## Payment Gateway:
17 | Real-world example using the Factory Method design pattern, but this time it simulates an online payment gateway system, with different connectors for PayPal and Stripe.
18 | ### Explanation:
19 | * PaymentProcessor is the abstract class defining the factory method getPaymentGateway().
20 | * PayPalProcessor and StripeProcessor are concrete implementations that return different payment gateway connectors.
21 | * PaymentGatewayConnector is the interface for all payment gateway operations.
22 | * PayPalConnector and StripeConnector implement the methods to handle the payment process.
23 | * clientCode() works with any processor (PayPal or Stripe) by calling the processPayment() method.
24 |
25 | This setup allows switching between different payment methods (PayPal, Stripe) without modifying the core client logic.
26 |
27 | ## Notification System:
28 | Another example, this time based on a notification system, where different types of notifications (Email, SMS) are created using the Factory Method design pattern.
29 |
30 | ### Explanation:
31 | * NotificationSender is the abstract class with the factory method getNotificationService().
32 | * EmailNotificationSender and SMSNotificationSender are concrete implementations of the factory method that return different notification services.
33 | * NotificationService is the interface for sending notifications (either via email or SMS).
34 | * EmailService and SMSService implement specific behaviors for sending notifications.
35 | * clientCode() uses any notification sender (Email or SMS) without changing the core logic.
36 |
37 | This setup allows flexibility in switching between different notification services (Email, SMS) as needed.
38 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Strategy/README.md:
--------------------------------------------------------------------------------
1 | # Strategy Pattern
2 |
3 | Strategy is a behavioral design pattern that turns a set of behaviors into objects and makes them interchangeable inside the original context object.
4 |
5 | The original object, called context, holds a reference to a strategy object. The context delegates executing the behavior to the linked strategy object. In order to change the way the context performs its work, other objects may replace the currently linked strategy object with another one.
6 |
7 | # Real World Example
8 | ## Payment Methods
9 | In this example, the Strategy pattern is used to represent payment methods in an e-commerce application.
10 |
11 | Each payment method can display a payment form to collect proper payment details from a user and send it to the payment processing company. Then, after the payment processing company redirects the user back to the application, the payment method will handle the response to complete the transaction.
12 |
13 | ### Examples of Payment Methods Implemented:
14 | 1. **Credit Card Payment (PHP)**
15 | - Displays a form to collect credit card details (e.g., card number, expiration date, CVV).
16 | - Sends the collected details to a credit card processing company.
17 | - Handles the response from the processing company.
18 |
19 | 2. **PayPal Payment (PHP)**
20 | - Redirects the user to PayPal to log in and approve the payment.
21 | - Handles the response from PayPal to complete the transaction.
22 |
23 | 3. **Bank Transfer Payment**
24 | - Displays a form to collect bank account details (e.g., account number, bank code).
25 | - Sends the collected details to a bank for processing the transfer.
26 | - Handles the response from the bank to confirm the payment.
27 |
28 | ### Main Example in PHP
29 | The main example of the Strategy pattern implemented in PHP demonstrates how different algorithms can be defined and encapsulated within separate classes. The context class then uses these strategies interchangeably.
30 |
31 | 1. **Context Class**:
32 | - Holds a reference to a strategy object.
33 | - Delegates executing the behavior to the linked strategy object.
34 |
35 | 2. **Strategy Interface**:
36 | - Defines a common interface for all concrete strategies.
37 |
38 | 3. **Concrete Strategies**:
39 | - Implement different algorithms that the context can use interchangeably.
40 |
41 | By using the Strategy pattern, the e-commerce application can easily switch between different payment methods without changing the code that handles the payment process. Each payment method implements a common interface, allowing the context object to interact with each method in a consistent manner. This makes the system flexible and easy to extend with new payment methods in the future.
42 |
--------------------------------------------------------------------------------
/patterns/Creational/Prototype/JavaScript/RealWorldExamples/ComplexPage.js:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Prototype Design Pattern - Complex Page Example
4 | |--------------------------------------------------------------------------
5 | | Implement Prototype Design Pattern to create objects without specifying
6 | | the exact class of object that will be created.
7 | |--------------------------------------------------------------------------
8 | | @category Design Pattern
9 | | @package Creational/Prototype/RealWorldExamples
10 | | @version 1.0.0
11 | | @license MIT License
12 | | @link https://github.com/JawherKl/design-patterns-in-js
13 | |--------------------------------------------------------------------------
14 | */
15 |
16 | class Page {
17 | constructor(title, body, author) {
18 | this.title = title;
19 | this.body = body;
20 | this.author = author;
21 | this.author.addToPage(this);
22 | this.comments = [];
23 | this.date = new Date();
24 | }
25 |
26 | addComment(comment) {
27 | this.comments.push(comment);
28 | }
29 |
30 | /**
31 | * You can control what data you want to carry over to the cloned object.
32 | *
33 | * For instance, when a page is cloned:
34 | * - It gets a new "Copy of ..." title.
35 | * - The author of the page remains the same. Therefore we leave the
36 | * reference to the existing object while adding the cloned page to the list
37 | * of the author's pages.
38 | * - We don't carry over the comments from the old page.
39 | * - We also attach a new date object to the page.
40 | */
41 | clone() {
42 | const clone = Object.create(Object.getPrototypeOf(this));
43 | clone.title = "Copy of " + this.title;
44 | clone.body = this.body;
45 | clone.author = this.author;
46 | clone.author.addToPage(clone);
47 | clone.comments = [];
48 | clone.date = new Date();
49 |
50 | return clone;
51 | }
52 | }
53 |
54 | class Author {
55 | constructor(name) {
56 | this.name = name;
57 | this.pages = [];
58 | }
59 |
60 | addToPage(page) {
61 | this.pages.push(page);
62 | }
63 | }
64 |
65 | /**
66 | * The client code.
67 | */
68 | function clientCode() {
69 | const author = new Author("John Smith");
70 | const page = new Page("Tip of the day", "Keep calm and carry on.", author);
71 |
72 | // ...
73 |
74 | page.addComment("Nice tip, thanks!");
75 |
76 | // ...
77 |
78 | const draft = page.clone();
79 | console.log("Dump of the clone. Note that the author is now referencing two objects.\n\n");
80 | console.log(draft);
81 | }
82 |
83 | clientCode();
84 |
--------------------------------------------------------------------------------
/patterns/Structural/Facade/PHP/RealWorldExample/MealOrder.php:
--------------------------------------------------------------------------------
1 | restaurant = new Restaurant();
34 | $this->deliveryService = new DeliveryService();
35 | $this->paymentProcessor = new PaymentProcessor();
36 | }
37 |
38 | public function placeOrder(string $meal, string $address, float $amount): void
39 | {
40 | echo "Placing order for: $meal...\n";
41 | $this->restaurant->prepareMeal($meal);
42 | $this->paymentProcessor->processPayment($amount);
43 | $this->deliveryService->deliverMeal($meal, $address);
44 | echo "Order completed successfully!\n";
45 | }
46 | }
47 |
48 | /**
49 | * Subsystem class responsible for meal preparation.
50 | */
51 | class Restaurant
52 | {
53 | public function prepareMeal(string $meal): void
54 | {
55 | echo "Preparing the meal: $meal...\n";
56 | }
57 | }
58 |
59 | /**
60 | * Subsystem class responsible for delivering the meal.
61 | */
62 | class DeliveryService
63 | {
64 | public function deliverMeal(string $meal, string $address): void
65 | {
66 | echo "Delivering $meal to $address...\n";
67 | }
68 | }
69 |
70 | /**
71 | * Subsystem class responsible for processing payments.
72 | */
73 | class PaymentProcessor
74 | {
75 | public function processPayment(float $amount): void
76 | {
77 | echo "Processing payment of $$amount...\n";
78 | }
79 | }
80 |
81 | /**
82 | * Client code using the Facade to place an order.
83 | */
84 | function clientCode(MealOrderFacade $facade)
85 | {
86 | $facade->placeOrder("Pizza Margherita", "123 Main St", 20.50);
87 | }
88 |
89 | $facade = new MealOrderFacade();
90 | clientCode($facade);
91 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/Java/RealWorldExample/ClientDatabaseFactory.java:
--------------------------------------------------------------------------------
1 | package patterns.Creational.AbstractFactory.Java.RealWorldExample;
2 |
3 | // Abstract Factory interface for creating database connections and queries
4 | interface DatabaseFactory {
5 | Connection createConnection();
6 | Query createQuery();
7 | }
8 |
9 | // Concrete Factory for MySQL database
10 | class MySQLFactory implements DatabaseFactory {
11 | @Override
12 | public Connection createConnection() {
13 | return new MySQLConnection();
14 | }
15 |
16 | @Override
17 | public Query createQuery() {
18 | return new MySQLQuery();
19 | }
20 | }
21 |
22 | // Concrete Factory for PostgreSQL database
23 | class PostgreSQLFactory implements DatabaseFactory {
24 | @Override
25 | public Connection createConnection() {
26 | return new PostgreSQLConnection();
27 | }
28 |
29 | @Override
30 | public Query createQuery() {
31 | return new PostgreSQLQuery();
32 | }
33 | }
34 |
35 | // Abstract product interface for database connections
36 | interface Connection {
37 | String connect();
38 | }
39 |
40 | // Concrete product for MySQL connection
41 | class MySQLConnection implements Connection {
42 | @Override
43 | public String connect() {
44 | return "Connected to MySQL database.";
45 | }
46 | }
47 |
48 | // Concrete product for PostgreSQL connection
49 | class PostgreSQLConnection implements Connection {
50 | @Override
51 | public String connect() {
52 | return "Connected to PostgreSQL database.";
53 | }
54 | }
55 |
56 | // Abstract product interface for database queries
57 | interface Query {
58 | String execute();
59 | }
60 |
61 | // Concrete product for MySQL query
62 | class MySQLQuery implements Query {
63 | @Override
64 | public String execute() {
65 | return "Executing MySQL query.";
66 | }
67 | }
68 |
69 | // Concrete product for PostgreSQL query
70 | class PostgreSQLQuery implements Query {
71 | @Override
72 | public String execute() {
73 | return "Executing PostgreSQL query.";
74 | }
75 | }
76 |
77 | // Client code
78 | public class ClientDatabaseFactory {
79 | public static void clientCode(DatabaseFactory factory) {
80 | Connection connection = factory.createConnection();
81 | System.out.println(connection.connect());
82 |
83 | Query query = factory.createQuery();
84 | System.out.println(query.execute());
85 | }
86 |
87 | public static void main(String[] args) {
88 | System.out.println("Testing MySQL factory:");
89 | clientCode(new MySQLFactory());
90 | System.out.println();
91 |
92 | System.out.println("Testing PostgreSQL factory:");
93 | clientCode(new PostgreSQLFactory());
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/patterns/Creational/Prototype/Go/RealWorldExamples/ComplexPage.go:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Prototype Design Pattern - Complex Page Example
4 | |--------------------------------------------------------------------------
5 | | Implement Prototype Design Pattern to create objects without specifying
6 | | the exact class of object that will be created.
7 | |--------------------------------------------------------------------------
8 | | @category Design Pattern
9 | | @package Creational/Prototype/RealWorldExamples
10 | | @version 1.0.0
11 | | @license MIT License
12 | | @link https://github.com/JawherKl/design-patterns-in-go
13 | |--------------------------------------------------------------------------
14 | */
15 |
16 | package main
17 |
18 | import (
19 | "fmt"
20 | "time"
21 | )
22 |
23 | // Page represents the Prototype.
24 | type Page struct {
25 | Title string
26 | Body string
27 | Author *Author
28 | Comments []string
29 | Date time.Time
30 | }
31 |
32 | // NewPage is the constructor for Page.
33 | func NewPage(title, body string, author *Author) *Page {
34 | page := &Page{
35 | Title: title,
36 | Body: body,
37 | Author: author,
38 | Comments: []string{},
39 | Date: time.Now(),
40 | }
41 | author.AddToPage(page)
42 | return page
43 | }
44 |
45 | // AddComment adds a comment to the Page.
46 | func (p *Page) AddComment(comment string) {
47 | p.Comments = append(p.Comments, comment)
48 | }
49 |
50 | // Clone creates a copy of the Page with certain modifications.
51 | func (p *Page) Clone() *Page {
52 | clone := *p
53 | clone.Title = "Copy of " + p.Title
54 | p.Author.AddToPage(&clone)
55 | clone.Comments = []string{}
56 | clone.Date = time.Now()
57 | return &clone
58 | }
59 |
60 | // Author represents the author of the Page.
61 | type Author struct {
62 | Name string
63 | Pages []*Page
64 | }
65 |
66 | // NewAuthor is the constructor for Author.
67 | func NewAuthor(name string) *Author {
68 | return &Author{
69 | Name: name,
70 | Pages: []*Page{},
71 | }
72 | }
73 |
74 | // AddToPage adds a Page to the Author's list of pages.
75 | func (a *Author) AddToPage(page *Page) {
76 | a.Pages = append(a.Pages, page)
77 | }
78 |
79 | // Client code demonstrating the Prototype Design Pattern.
80 | func clientCode() {
81 | author := NewAuthor("John Smith")
82 | page := NewPage("Tip of the day", "Keep calm and carry on.", author)
83 |
84 | // ...
85 |
86 | page.AddComment("Nice tip, thanks!")
87 |
88 | // ...
89 |
90 | draft := page.Clone()
91 | fmt.Println("Dump of the clone. Note that the author is now referencing two objects.")
92 | fmt.Printf("%+v\n", draft)
93 | }
94 |
95 | func main() {
96 | clientCode()
97 | }
98 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/JavaScript/RealWorldExample/NotificationServices.js:
--------------------------------------------------------------------------------
1 | // NotificationFactory.js - Abstract Factory for creating notification services
2 | class NotificationFactory {
3 | createEmailService() {
4 | throw new Error("Method 'createEmailService()' must be implemented.");
5 | }
6 |
7 | createSMSService() {
8 | throw new Error("Method 'createSMSService()' must be implemented.");
9 | }
10 | }
11 |
12 | // GmailFactory.js - Concrete Factory for Gmail notification services
13 | class GmailFactory extends NotificationFactory {
14 | createEmailService() {
15 | return new GmailEmailService();
16 | }
17 |
18 | createSMSService() {
19 | return new GmailSMSService();
20 | }
21 | }
22 |
23 | // YahooFactory.js - Concrete Factory for Yahoo notification services
24 | class YahooFactory extends NotificationFactory {
25 | createEmailService() {
26 | return new YahooEmailService();
27 | }
28 |
29 | createSMSService() {
30 | return new YahooSMSService();
31 | }
32 | }
33 |
34 | // EmailService.js - Abstract product interface for email services
35 | class EmailService {
36 | sendEmail() {
37 | throw new Error("Method 'sendEmail()' must be implemented.");
38 | }
39 | }
40 |
41 | // GmailEmailService.js - Concrete product for Gmail email service
42 | class GmailEmailService extends EmailService {
43 | sendEmail() {
44 | return "Sending email via Gmail.";
45 | }
46 | }
47 |
48 | // YahooEmailService.js - Concrete product for Yahoo email service
49 | class YahooEmailService extends EmailService {
50 | sendEmail() {
51 | return "Sending email via Yahoo.";
52 | }
53 | }
54 |
55 | // SMSService.js - Abstract product interface for SMS services
56 | class SMSService {
57 | sendSMS() {
58 | throw new Error("Method 'sendSMS()' must be implemented.");
59 | }
60 | }
61 |
62 | // GmailSMSService.js - Concrete product for Gmail SMS service
63 | class GmailSMSService extends SMSService {
64 | sendSMS() {
65 | return "Sending SMS via Gmail.";
66 | }
67 | }
68 |
69 | // YahooSMSService.js - Concrete product for Yahoo SMS service
70 | class YahooSMSService extends SMSService {
71 | sendSMS() {
72 | return "Sending SMS via Yahoo.";
73 | }
74 | }
75 |
76 | // Client.js - Client code
77 | function sendNotifications(factory) {
78 | const emailService = factory.createEmailService();
79 | console.log(emailService.sendEmail());
80 |
81 | const smsService = factory.createSMSService();
82 | console.log(smsService.sendSMS());
83 | }
84 |
85 | // Usage
86 | console.log("Testing Gmail notification factory:");
87 | sendNotifications(new GmailFactory());
88 | console.log("\n");
89 |
90 | console.log("Testing Yahoo notification factory:");
91 | sendNotifications(new YahooFactory());
92 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/Java/RealWorldExample/ClientNotificationFactory.java:
--------------------------------------------------------------------------------
1 | package patterns.Creational.AbstractFactory.Java.RealWorldExample;
2 |
3 | // Abstract Factory for creating notification services
4 | interface NotificationFactory {
5 | EmailService createEmailService();
6 | SMSService createSMSService();
7 | }
8 |
9 | // Concrete Factory for Gmail notification services
10 | class GmailFactory implements NotificationFactory {
11 | @Override
12 | public EmailService createEmailService() {
13 | return new GmailEmailService();
14 | }
15 |
16 | @Override
17 | public SMSService createSMSService() {
18 | return new GmailSMSService();
19 | }
20 | }
21 |
22 | // Concrete Factory for Yahoo notification services
23 | class YahooFactory implements NotificationFactory {
24 | @Override
25 | public EmailService createEmailService() {
26 | return new YahooEmailService();
27 | }
28 |
29 | @Override
30 | public SMSService createSMSService() {
31 | return new YahooSMSService();
32 | }
33 | }
34 |
35 | // Abstract product interface for email services
36 | interface EmailService {
37 | String sendEmail();
38 | }
39 |
40 | // Concrete product for Gmail email service
41 | class GmailEmailService implements EmailService {
42 | @Override
43 | public String sendEmail() {
44 | return "Sending email via Gmail.";
45 | }
46 | }
47 |
48 | // Concrete product for Yahoo email service
49 | class YahooEmailService implements EmailService {
50 | @Override
51 | public String sendEmail() {
52 | return "Sending email via Yahoo.";
53 | }
54 | }
55 |
56 | // Abstract product interface for SMS services
57 | interface SMSService {
58 | String sendSMS();
59 | }
60 |
61 | // Concrete product for Gmail SMS service
62 | class GmailSMSService implements SMSService {
63 | @Override
64 | public String sendSMS() {
65 | return "Sending SMS via Gmail.";
66 | }
67 | }
68 |
69 | // Concrete product for Yahoo SMS service
70 | class YahooSMSService implements SMSService {
71 | @Override
72 | public String sendSMS() {
73 | return "Sending SMS via Yahoo.";
74 | }
75 | }
76 |
77 | // Client code
78 | public class ClientNotificationFactory {
79 | public static void sendNotifications(NotificationFactory factory) {
80 | EmailService emailService = factory.createEmailService();
81 | System.out.println(emailService.sendEmail());
82 |
83 | SMSService smsService = factory.createSMSService();
84 | System.out.println(smsService.sendSMS());
85 | }
86 |
87 | public static void main(String[] args) {
88 | System.out.println("Testing Gmail notification factory:");
89 | sendNotifications(new GmailFactory());
90 | System.out.println();
91 |
92 | System.out.println("Testing Yahoo notification factory:");
93 | sendNotifications(new YahooFactory());
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/patterns/Creational/Builder/JavaScript/RealWorldExample/SQLQueryBuilder.js:
--------------------------------------------------------------------------------
1 | // Builder Design Pattern - SQL Query Builder
2 | //
3 | // This example demonstrates the Factory Method Design Pattern to send various
4 | // types of notifications (Email, SMS).
5 |
6 | // SQLQueryBuilder interface declares a set of methods to assemble an SQL query.
7 | class SQLQueryBuilder {
8 | select(table, fields) {}
9 | where(field, value, operator = '=') {}
10 | limit(start, offset) {}
11 | getSQL() {}
12 | }
13 |
14 | // Concrete Builder for MySQL SQL queries.
15 | class MysqlQueryBuilder extends SQLQueryBuilder {
16 | constructor() {
17 | super();
18 | this.reset();
19 | }
20 |
21 | reset() {
22 | this.query = {};
23 | }
24 |
25 | select(table, fields) {
26 | this.reset();
27 | this.query.base = `SELECT ${fields.join(', ')} FROM ${table}`;
28 | this.query.type = 'select';
29 | return this;
30 | }
31 |
32 | where(field, value, operator = '=') {
33 | if (!['select', 'update', 'delete'].includes(this.query.type)) {
34 | throw new Error('WHERE can only be added to SELECT, UPDATE OR DELETE');
35 | }
36 | if (!this.query.where) {
37 | this.query.where = [];
38 | }
39 | this.query.where.push(`${field} ${operator} '${value}'`);
40 | return this;
41 | }
42 |
43 | limit(start, offset) {
44 | if (!['select'].includes(this.query.type)) {
45 | throw new Error('LIMIT can only be added to SELECT');
46 | }
47 | this.query.limit = ` LIMIT ${start}, ${offset}`;
48 | return this;
49 | }
50 |
51 | getSQL() {
52 | let sql = this.query.base;
53 | if (this.query.where && this.query.where.length > 0) {
54 | sql += ` WHERE ${this.query.where.join(' AND ')}`;
55 | }
56 | if (this.query.limit) {
57 | sql += this.query.limit;
58 | }
59 | return sql + ';';
60 | }
61 | }
62 |
63 | // Concrete Builder for PostgreSQL SQL queries.
64 | class PostgresQueryBuilder extends MysqlQueryBuilder {
65 | limit(start, offset) {
66 | super.limit(start, offset);
67 | this.query.limit = ` LIMIT ${start} OFFSET ${offset}`;
68 | return this;
69 | }
70 | }
71 |
72 | // Client code to demonstrate the SQL Query Builder.
73 | function clientCode(builder) {
74 | const query = builder.select('users', ['name', 'email', 'password'])
75 | .where('age', '18', '>')
76 | .where('age', '30', '<')
77 | .limit(10, 20)
78 | .getSQL();
79 |
80 | console.log(query);
81 | }
82 |
83 | console.log('Testing MySQL query builder:');
84 | clientCode(new MysqlQueryBuilder());
85 | console.log();
86 |
87 | console.log('Testing PostgreSQL query builder:');
88 | clientCode(new PostgresQueryBuilder());
89 | console.log();
90 |
--------------------------------------------------------------------------------
/patterns/Structural/Adapter/PHP/Adapter.php:
--------------------------------------------------------------------------------
1 | adaptee = $adaptee;
63 | }
64 |
65 | public function request(): string
66 | {
67 | return "Adapter: (TRANSLATED) " . strrev($this->adaptee->specificRequest());
68 | }
69 | }
70 |
71 | /**
72 | * The client code supports all classes that follow the Target interface.
73 | */
74 | function clientCode(Target $target)
75 | {
76 | echo $target->request();
77 | }
78 |
79 | echo "Client: I can work just fine with the Target objects:\n";
80 | $target = new Target();
81 | clientCode($target);
82 | echo "\n\n";
83 |
84 | $adaptee = new Adaptee();
85 | echo "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";
86 | echo "Adaptee: " . $adaptee->specificRequest();
87 | echo "\n\n";
88 |
89 | echo "Client: But I can work with it via the Adapter:\n";
90 | $adapter = new Adapter($adaptee);
91 | clientCode($adapter);
--------------------------------------------------------------------------------
/patterns/Creational/Prototype/README.md:
--------------------------------------------------------------------------------
1 | Prototype is a creational design pattern that lets you copy existing objects without making your code dependent on their classes.
2 |
3 | # Conceptual Example:
4 | This example illustrates the structure of the Prototype design pattern and focuses on the following questions:
5 | * What classes does it consist of?
6 | * What roles do these classes play?
7 | * In what way the elements of the pattern are related?
8 |
9 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
10 |
11 | # Real World Example:
12 | ## Complex Page:
13 | The Prototype pattern provides a convenient way of replicating existing objects instead of trying to reconstruct the objects by copying all of their fields directly. The direct approach not only couples you to the classes of the objects being cloned, but also doesn’t allow you to copy the contents of the private fields. The Prototype pattern lets you perform the cloning within the context of the cloned class, where the access to the class’ private fields isn’t restricted.
14 |
15 | This example shows you how to clone a complex Page object using the Prototype pattern. The Page class has lots of private fields, which will be carried over to the cloned object thanks to the Prototype pattern.
16 |
17 | ## Document
18 | ### Explanation:
19 | * Purpose: The Prototype Design Pattern allows creating new objects by cloning existing ones rather than instantiating them from scratch. This can save time, especially when object creation is complex.
20 | * Classes:
21 | * Prototype Interface: Defines a __clone() method that must be implemented by concrete prototypes.
22 | * Document: A concrete implementation of the prototype, where we specify which fields to carry over or modify during cloning.
23 | * Author: Contains a reference to multiple documents, shared across cloned documents.
24 |
25 | Client Code: It demonstrates creating a document and then cloning it. The cloned document has its title updated but retains a reference to the same author.
26 |
27 | ## Shape
28 | ### Explanation:
29 | * Purpose: This example demonstrates how to clone shapes (like circles and rectangles) using the Prototype Design Pattern. Each shape can be duplicated without the need for recalculating or recreating it from scratch.
30 | * Classes:
31 | * ShapePrototype: The interface that declares the __clone() method for all shapes.
32 | * Shape: An abstract class that implements basic shape behavior, including color handling.
33 | * Circle: A concrete shape that holds a radius and implements the __clone() method.
34 | * Rectangle: A concrete shape with width and height, also supporting cloning.
35 | * Client Code: It creates and clones a circle and a rectangle, altering properties (e.g., color) in the cloned versions while keeping the originals intact.
36 |
37 | This pattern is useful when you have expensive or complex initialization processes that you want to avoid by simply copying existing objects.
38 |
--------------------------------------------------------------------------------
/patterns/Behavioral/State/PHP/State.php:
--------------------------------------------------------------------------------
1 | transitionTo($state);
20 | }
21 |
22 | /**
23 | * The Context allows changing the State object at runtime.
24 | */
25 | public function transitionTo(State $state): void
26 | {
27 | echo "Context: Transition to " . get_class($state) . ".\n";
28 | $this->state = $state;
29 | $this->state->setContext($this);
30 | }
31 |
32 | /**
33 | * The Context delegates part of its behavior to the current State object.
34 | */
35 | public function request1(): void
36 | {
37 | $this->state->handle1();
38 | }
39 |
40 | public function request2(): void
41 | {
42 | $this->state->handle2();
43 | }
44 | }
45 |
46 | /**
47 | * The base State class declares methods that all Concrete State should
48 | * implement and also provides a backreference to the Context object, associated
49 | * with the State. This backreference can be used by States to transition the
50 | * Context to another State.
51 | */
52 | abstract class State
53 | {
54 | /**
55 | * @var Context
56 | */
57 | protected $context;
58 |
59 | public function setContext(Context $context)
60 | {
61 | $this->context = $context;
62 | }
63 |
64 | abstract public function handle1(): void;
65 |
66 | abstract public function handle2(): void;
67 | }
68 |
69 | /**
70 | * Concrete States implement various behaviors, associated with a state of the
71 | * Context.
72 | */
73 | class ConcreteStateA extends State
74 | {
75 | public function handle1(): void
76 | {
77 | echo "ConcreteStateA handles request1.\n";
78 | echo "ConcreteStateA wants to change the state of the context.\n";
79 | $this->context->transitionTo(new ConcreteStateB());
80 | }
81 |
82 | public function handle2(): void
83 | {
84 | echo "ConcreteStateA handles request2.\n";
85 | }
86 | }
87 |
88 | class ConcreteStateB extends State
89 | {
90 | public function handle1(): void
91 | {
92 | echo "ConcreteStateB handles request1.\n";
93 | }
94 |
95 | public function handle2(): void
96 | {
97 | echo "ConcreteStateB handles request2.\n";
98 | echo "ConcreteStateB wants to change the state of the context.\n";
99 | $this->context->transitionTo(new ConcreteStateA());
100 | }
101 | }
102 |
103 | /**
104 | * The client code.
105 | */
106 | $context = new Context(new ConcreteStateA());
107 | $context->request1();
108 | $context->request2();
--------------------------------------------------------------------------------
/patterns/Behavioral/Command/JavaScript/Command.js:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Command Design Pattern
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Command Design Pattern
6 | |--------------------------------------------------------------------------
7 | | @category Design Pattern
8 | | @package Behavioral/Command
9 | | @version 1.0.0
10 | | @license MIT License
11 | | @link https://github.com/JawherKl/design-patterns-in-php
12 | |--------------------------------------------------------------------------
13 | |
14 | */
15 |
16 | // Command interface declares a method for executing a command.
17 | class Command {
18 | execute() {}
19 | }
20 |
21 | // Some commands can implement simple operations on their own.
22 | class SimpleCommand extends Command {
23 | constructor(payload) {
24 | super();
25 | this.payload = payload;
26 | }
27 |
28 | execute() {
29 | console.log(`SimpleCommand: See, I can do simple things like printing (${this.payload})`);
30 | }
31 | }
32 |
33 | // However, some commands can delegate more complex operations to other objects, called "receivers."
34 | class ComplexCommand extends Command {
35 | constructor(receiver, a, b) {
36 | super();
37 | this.receiver = receiver;
38 | this.a = a;
39 | this.b = b;
40 | }
41 |
42 | execute() {
43 | console.log("ComplexCommand: Complex stuff should be done by a receiver object.");
44 | this.receiver.doSomething(this.a);
45 | this.receiver.doSomethingElse(this.b);
46 | }
47 | }
48 |
49 | // The Receiver classes contain some important business logic. They know how to perform all kinds of operations, associated with carrying out a request. In fact, any class may serve as a Receiver.
50 | class Receiver {
51 | doSomething(a) {
52 | console.log(`Receiver: Working on (${a}).`);
53 | }
54 |
55 | doSomethingElse(b) {
56 | console.log(`Receiver: Also working on (${b}).`);
57 | }
58 | }
59 |
60 | // The Invoker is associated with one or several commands. It sends a request to the command.
61 | class Invoker {
62 | setOnStart(command) {
63 | this.onStart = command;
64 | }
65 |
66 | setOnFinish(command) {
67 | this.onFinish = command;
68 | }
69 |
70 | doSomethingImportant() {
71 | console.log("Invoker: Does anybody want something done before I begin?");
72 | if (this.onStart instanceof Command) {
73 | this.onStart.execute();
74 | }
75 |
76 | console.log("Invoker: ...doing something really important...");
77 |
78 | console.log("Invoker: Does anybody want something done after I finish?");
79 | if (this.onFinish instanceof Command) {
80 | this.onFinish.execute();
81 | }
82 | }
83 | }
84 |
85 | // The client code can parameterize an invoker with any commands.
86 | const invoker = new Invoker();
87 | invoker.setOnStart(new SimpleCommand("Say Hi!"));
88 | const receiver = new Receiver();
89 | invoker.setOnFinish(new ComplexCommand(receiver, "Send email", "Save report"));
90 |
91 | invoker.doSomethingImportant();
92 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Memento/PHP/RealWorldExample/TextEditor.php:
--------------------------------------------------------------------------------
1 | content = $content;
15 | }
16 |
17 | public function getContent(): string
18 | {
19 | return $this->content;
20 | }
21 | }
22 |
23 | /**
24 | * The TextEditor class holds the state (content of the text) and can create and restore Mementos.
25 | */
26 | class TextEditor
27 | {
28 | private $content;
29 |
30 | public function __construct(string $content = "")
31 | {
32 | $this->content = $content;
33 | }
34 |
35 | public function setContent(string $content): void
36 | {
37 | $this->content = $content;
38 | }
39 |
40 | public function getContent(): string
41 | {
42 | return $this->content;
43 | }
44 |
45 | // Create a Memento with the current content
46 | public function save(): Memento
47 | {
48 | echo "TextEditor: Saving current content to Memento.\n";
49 | return new Memento($this->content);
50 | }
51 |
52 | // Restore content from a Memento
53 | public function restore(Memento $memento): void
54 | {
55 | $this->content = $memento->getContent();
56 | echo "TextEditor: Restoring content from Memento: " . $this->content . "\n";
57 | }
58 | }
59 |
60 | /**
61 | * The History class acts as a caretaker for saving and retrieving Mementos.
62 | */
63 | class History
64 | {
65 | private $mementos = [];
66 |
67 | // Add a Memento to the history
68 | public function addMemento(Memento $memento): void
69 | {
70 | $this->mementos[] = $memento;
71 | }
72 |
73 | // Retrieve a Memento from the history
74 | public function getMemento(int $index): Memento
75 | {
76 | return $this->mementos[$index];
77 | }
78 | }
79 |
80 | // Client code
81 | $editor = new TextEditor("Hello World!");
82 | $history = new History();
83 |
84 | // Save the current state of the editor
85 | $history->addMemento($editor->save());
86 |
87 | // Modify the text
88 | $editor->setContent("Hello, PHP World!");
89 |
90 | // Save the new state
91 | $history->addMemento($editor->save());
92 |
93 | // Modify the text again
94 | $editor->setContent("Hello, Memento Pattern!");
95 |
96 | // Print current content
97 | echo "Current content: " . $editor->getContent() . "\n";
98 |
99 | // Restore to the previous state (Hello, PHP World!)
100 | $editor->restore($history->getMemento(1));
101 |
102 | // Print the restored content
103 | echo "Restored content: " . $editor->getContent() . "\n";
104 |
105 | // Restore to the initial state (Hello World!)
106 | $editor->restore($history->getMemento(0));
107 |
108 | // Print the initial restored content
109 | echo "Initial content: " . $editor->getContent() . "\n";
110 |
111 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Iterator/PHP/Iterator.php:
--------------------------------------------------------------------------------
1 | collection = $collection;
31 | $this->reverse = $reverse;
32 | }
33 |
34 | public function rewind()
35 | {
36 | $this->position = $this->reverse ?
37 | count($this->collection->getItems()) - 1 : 0;
38 | }
39 |
40 | public function current()
41 | {
42 | return $this->collection->getItems()[$this->position];
43 | }
44 |
45 | public function key()
46 | {
47 | return $this->position;
48 | }
49 |
50 | public function next()
51 | {
52 | $this->position = $this->position + ($this->reverse ? -1 : 1);
53 | }
54 |
55 | public function valid()
56 | {
57 | return isset($this->collection->getItems()[$this->position]);
58 | }
59 | }
60 |
61 | /**
62 | * Concrete Collections provide one or several methods for retrieving fresh
63 | * iterator instances, compatible with the collection class.
64 | */
65 | class WordsCollection implements \IteratorAggregate
66 | {
67 | private $items = [];
68 |
69 | public function getItems()
70 | {
71 | return $this->items;
72 | }
73 |
74 | public function addItem($item)
75 | {
76 | $this->items[] = $item;
77 | }
78 |
79 | public function getIterator(): \Iterator
80 | {
81 | return new AlphabeticalOrderIterator($this);
82 | }
83 |
84 | public function getReverseIterator(): \Iterator
85 | {
86 | return new AlphabeticalOrderIterator($this, true);
87 | }
88 | }
89 |
90 | /**
91 | * The client code may or may not know about the Concrete Iterator or Collection
92 | * classes, depending on the level of indirection you want to keep in your
93 | * program.
94 | */
95 | $collection = new WordsCollection();
96 | $collection->addItem("First");
97 | $collection->addItem("Second");
98 | $collection->addItem("Third");
99 |
100 | echo "Straight traversal:\n";
101 | foreach ($collection->getIterator() as $item) {
102 | echo $item . "\n";
103 | }
104 |
105 | echo "\n";
106 | echo "Reverse traversal:\n";
107 | foreach ($collection->getReverseIterator() as $item) {
108 | echo $item . "\n";
109 | }
110 | ?>
111 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Mediator/PHP/Mediator.php:
--------------------------------------------------------------------------------
1 | component1 = $c1;
28 | $this->component1->setMediator($this);
29 | $this->component2 = $c2;
30 | $this->component2->setMediator($this);
31 | }
32 |
33 | public function notify(object $sender, string $event): void
34 | {
35 | if ($event == "A") {
36 | echo "Mediator reacts on A and triggers following operations:\n";
37 | $this->component2->doC();
38 | }
39 |
40 | if ($event == "D") {
41 | echo "Mediator reacts on D and triggers following operations:\n";
42 | $this->component1->doB();
43 | $this->component2->doC();
44 | }
45 | }
46 | }
47 |
48 | /**
49 | * The Base Component provides the basic functionality of storing a mediator's
50 | * instance inside component objects.
51 | */
52 | class BaseComponent
53 | {
54 | protected $mediator;
55 |
56 | public function __construct(Mediator $mediator = null)
57 | {
58 | $this->mediator = $mediator;
59 | }
60 |
61 | public function setMediator(Mediator $mediator): void
62 | {
63 | $this->mediator = $mediator;
64 | }
65 | }
66 |
67 | /**
68 | * Concrete Components implement various functionality. They don't depend on
69 | * other components. They also don't depend on any concrete mediator classes.
70 | */
71 | class Component1 extends BaseComponent
72 | {
73 | public function doA(): void
74 | {
75 | echo "Component 1 does A.\n";
76 | $this->mediator->notify($this, "A");
77 | }
78 |
79 | public function doB(): void
80 | {
81 | echo "Component 1 does B.\n";
82 | $this->mediator->notify($this, "B");
83 | }
84 | }
85 |
86 | class Component2 extends BaseComponent
87 | {
88 | public function doC(): void
89 | {
90 | echo "Component 2 does C.\n";
91 | $this->mediator->notify($this, "C");
92 | }
93 |
94 | public function doD(): void
95 | {
96 | echo "Component 2 does D.\n";
97 | $this->mediator->notify($this, "D");
98 | }
99 | }
100 |
101 | /**
102 | * The client code.
103 | */
104 | $c1 = new Component1();
105 | $c2 = new Component2();
106 | $mediator = new ConcreteMediator($c1, $c2);
107 |
108 | echo "Client triggers operation A.\n";
109 | $c1->doA();
110 |
111 | echo "\n";
112 | echo "Client triggers operation D.\n";
113 | $c2->doD();
114 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Command/Go/Command.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | /*
6 | |--------------------------------------------------------------------------
7 | | Command Design Pattern
8 | |--------------------------------------------------------------------------
9 | | This example demonstrates the Command Design Pattern
10 | |--------------------------------------------------------------------------
11 | | @category Design Pattern
12 | | @package Behavioral/Command
13 | | @version 1.0.0
14 | | @license MIT License
15 | | @link https://github.com/JawherKl/design-patterns-in-php
16 | |--------------------------------------------------------------------------
17 | */
18 |
19 | // Command interface declares a method for executing a command.
20 | type Command interface {
21 | Execute()
22 | }
23 |
24 | // SimpleCommand implements the Command interface for simple operations.
25 | type SimpleCommand struct {
26 | payload string
27 | }
28 |
29 | func NewSimpleCommand(payload string) *SimpleCommand {
30 | return &SimpleCommand{payload: payload}
31 | }
32 |
33 | func (s *SimpleCommand) Execute() {
34 | fmt.Printf("SimpleCommand: See, I can do simple things like printing (%s)\n", s.payload)
35 | }
36 |
37 | // ComplexCommand delegates more complex operations to a Receiver.
38 | type ComplexCommand struct {
39 | receiver *Receiver
40 | a string
41 | b string
42 | }
43 |
44 | func NewComplexCommand(receiver *Receiver, a string, b string) *ComplexCommand {
45 | return &ComplexCommand{receiver: receiver, a: a, b: b}
46 | }
47 |
48 | func (c *ComplexCommand) Execute() {
49 | fmt.Println("ComplexCommand: Complex stuff should be done by a receiver object.")
50 | c.receiver.DoSomething(c.a)
51 | c.receiver.DoSomethingElse(c.b)
52 | }
53 |
54 | // Receiver contains business logic and knows how to perform operations.
55 | type Receiver struct{}
56 |
57 | func (r *Receiver) DoSomething(a string) {
58 | fmt.Printf("Receiver: Working on (%s.)\n", a)
59 | }
60 |
61 | func (r *Receiver) DoSomethingElse(b string) {
62 | fmt.Printf("Receiver: Also working on (%s.)\n", b)
63 | }
64 |
65 | // Invoker is associated with commands and sends requests to them.
66 | type Invoker struct {
67 | onStart Command
68 | onFinish Command
69 | }
70 |
71 | func (i *Invoker) SetOnStart(command Command) {
72 | i.onStart = command
73 | }
74 |
75 | func (i *Invoker) SetOnFinish(command Command) {
76 | i.onFinish = command
77 | }
78 |
79 | func (i *Invoker) DoSomethingImportant() {
80 | fmt.Println("Invoker: Does anybody want something done before I begin?")
81 | if i.onStart != nil {
82 | i.onStart.Execute()
83 | }
84 |
85 | fmt.Println("Invoker: ...doing something really important...")
86 |
87 | fmt.Println("Invoker: Does anybody want something done after I finish?")
88 | if i.onFinish != nil {
89 | i.onFinish.Execute()
90 | }
91 | }
92 |
93 | // Client code parameterizes an invoker with commands.
94 | func main() {
95 | invoker := &Invoker{}
96 | invoker.SetOnStart(NewSimpleCommand("Say Hi!"))
97 | receiver := &Receiver{}
98 | invoker.SetOnFinish(NewComplexCommand(receiver, "Send email", "Save report"))
99 |
100 | invoker.DoSomethingImportant()
101 | }
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/Go/AbstractFactory.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // Abstract Factory interface declares methods to create abstract products
6 | type AbstractFactory interface {
7 | CreateProductA() AbstractProductA
8 | CreateProductB() AbstractProductB
9 | }
10 |
11 | // Concrete Factory 1 produces ProductA1 and ProductB1
12 | type ConcreteFactory1 struct{}
13 |
14 | func (f *ConcreteFactory1) CreateProductA() AbstractProductA {
15 | return &ConcreteProductA1{}
16 | }
17 |
18 | func (f *ConcreteFactory1) CreateProductB() AbstractProductB {
19 | return &ConcreteProductB1{}
20 | }
21 |
22 | // Concrete Factory 2 produces ProductA2 and ProductB2
23 | type ConcreteFactory2 struct{}
24 |
25 | func (f *ConcreteFactory2) CreateProductA() AbstractProductA {
26 | return &ConcreteProductA2{}
27 | }
28 |
29 | func (f *ConcreteFactory2) CreateProductB() AbstractProductB {
30 | return &ConcreteProductB2{}
31 | }
32 |
33 | // Abstract ProductA interface defines methods that ProductA must implement
34 | type AbstractProductA interface {
35 | UsefulFunctionA() string
36 | }
37 |
38 | // Concrete ProductA1 implements the AbstractProductA interface
39 | type ConcreteProductA1 struct{}
40 |
41 | func (p *ConcreteProductA1) UsefulFunctionA() string {
42 | return "The result of the product A1."
43 | }
44 |
45 | // Concrete ProductA2 implements the AbstractProductA interface
46 | type ConcreteProductA2 struct{}
47 |
48 | func (p *ConcreteProductA2) UsefulFunctionA() string {
49 | return "The result of the product A2."
50 | }
51 |
52 | // Abstract ProductB interface defines methods that ProductB must implement
53 | type AbstractProductB interface {
54 | UsefulFunctionB() string
55 | AnotherUsefulFunctionB(collaborator AbstractProductA) string
56 | }
57 |
58 | // Concrete ProductB1 implements the AbstractProductB interface
59 | type ConcreteProductB1 struct{}
60 |
61 | func (p *ConcreteProductB1) UsefulFunctionB() string {
62 | return "The result of the product B1."
63 | }
64 |
65 | func (p *ConcreteProductB1) AnotherUsefulFunctionB(collaborator AbstractProductA) string {
66 | result := collaborator.UsefulFunctionA()
67 | return fmt.Sprintf("The result of B1 collaborating with the (%s)", result)
68 | }
69 |
70 | // Concrete ProductB2 implements the AbstractProductB interface
71 | type ConcreteProductB2 struct{}
72 |
73 | func (p *ConcreteProductB2) UsefulFunctionB() string {
74 | return "The result of the product B2."
75 | }
76 |
77 | func (p *ConcreteProductB2) AnotherUsefulFunctionB(collaborator AbstractProductA) string {
78 | result := collaborator.UsefulFunctionA()
79 | return fmt.Sprintf("The result of B2 collaborating with the (%s)", result)
80 | }
81 |
82 | // Client code that works with the abstract factory and products
83 | func clientCode(factory AbstractFactory) {
84 | productA := factory.CreateProductA()
85 | productB := factory.CreateProductB()
86 |
87 | fmt.Println(productB.UsefulFunctionB())
88 | fmt.Println(productB.AnotherUsefulFunctionB(productA))
89 | }
90 |
91 | func main() {
92 | fmt.Println("Client: Testing client code with the first factory type:")
93 | clientCode(&ConcreteFactory1{})
94 |
95 | fmt.Println("\nClient: Testing the same client code with the second factory type:")
96 | clientCode(&ConcreteFactory2{})
97 | }
98 |
--------------------------------------------------------------------------------
/patterns/Structural/Facade/PHP/RealWorldExample/HomeAutomation.php:
--------------------------------------------------------------------------------
1 | lights = new SmartLights();
32 | $this->thermostat = new Thermostat();
33 | $this->securitySystem = new SecuritySystem();
34 | }
35 |
36 | public function startMorningRoutine(): void
37 | {
38 | echo "Starting morning routine...\n";
39 | $this->lights->turnOn();
40 | $this->thermostat->setTemperature(22);
41 | $this->securitySystem->deactivate();
42 | echo "Morning routine complete!\n";
43 | }
44 |
45 | public function startNightRoutine(): void
46 | {
47 | echo "Starting night routine...\n";
48 | $this->lights->dim();
49 | $this->thermostat->setTemperature(18);
50 | $this->securitySystem->activate();
51 | echo "Night routine complete!\n";
52 | }
53 | }
54 |
55 | /**
56 | * Subsystem class for controlling the lights.
57 | */
58 | class SmartLights
59 | {
60 | public function turnOn(): void
61 | {
62 | echo "Turning on the lights...\n";
63 | }
64 |
65 | public function dim(): void
66 | {
67 | echo "Dimming the lights...\n";
68 | }
69 | }
70 |
71 | /**
72 | * Subsystem class for controlling the thermostat.
73 | */
74 | class Thermostat
75 | {
76 | public function setTemperature(int $temperature): void
77 | {
78 | echo "Setting temperature to $temperature °C...\n";
79 | }
80 | }
81 |
82 | /**
83 | * Subsystem class for managing the security system.
84 | */
85 | class SecuritySystem
86 | {
87 | public function activate(): void
88 | {
89 | echo "Activating the security system...\n";
90 | }
91 |
92 | public function deactivate(): void
93 | {
94 | echo "Deactivating the security system...\n";
95 | }
96 | }
97 |
98 | /**
99 | * Client code using the Facade to control the smart home system.
100 | */
101 | function clientCode(SmartHomeFacade $facade)
102 | {
103 | echo "\n--- Morning Routine ---\n";
104 | $facade->startMorningRoutine();
105 |
106 | echo "\n--- Night Routine ---\n";
107 | $facade->startNightRoutine();
108 | }
109 |
110 | $facade = new SmartHomeFacade();
111 | clientCode($facade);
112 |
--------------------------------------------------------------------------------
/patterns/Structural/Bridge/README.md:
--------------------------------------------------------------------------------
1 | Bridge is a structural design pattern that 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 of each other.
2 |
3 | The Bridge pattern is especially useful when supporting multiple types of database servers or working with several API providers of a certain kind (for example, cloud platforms, social networks, etc.)
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Bridge design pattern and focuses on the following questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## DeviceController
15 | This demonstrates how the Bridge Design Pattern decouples the abstraction `DeviceController` from the implementation `Device`, enabling both to evolve independently
16 |
17 | ## Page
18 | In this example, the `Page` hierarchy acts as the Abstraction, and the `Renderer` hierarchy acts as the Implementation. Objects of the `Page` class can assemble web pages of a particular kind using basic elements provided by a `Renderer` object attached to that page. Since both of the class hierarchies are separate, you can add a new `Renderer` class without changing any of the `Page` classes and vice versa.
19 |
20 | ## PaymentSystem
21 | This example demonstrates how the Bridge Design Pattern allows separating the abstraction (Payment) from the implementation (PaymentGateway), enabling flexibility to add new payment types or gateways without affecting existing code.
22 |
23 | ### Explanation:
24 | * Abstraction (Payment):
25 | -Represents the main operations of the payment system.
26 | -Delegates the processing of payments to the PaymentGateway implementation.
27 | * Refined Abstractions (OnlinePayment, InStorePayment):
28 | -Provide specific implementations for payment types (online or in-store).
29 | * Implementation (PaymentGateway Interface):
30 | -Represents the interface for payment gateways like PayPal or Stripe.
31 | * Concrete Implementations (PayPalGateway, StripeGateway):
32 | -Specific implementations for different payment gateways.
33 | * Client Code:
34 | -Works only with the abstraction, not caring about the specific implementation.
35 |
36 | ## CurrencyConverter:
37 | In this scenario, we'll implement a drawing tool where the abstraction represents different shapes (like circles and rectangles), and the implementation focuses on different rendering methods (like vector rendering and raster rendering).
38 | ### Explanation:
39 | * Abstraction (Shape):
40 | -Represents the concept of a shape.
41 | -Delegates the rendering logic to the Renderer implementation.
42 | * Refined Abstractions (Circle, Rectangle):
43 | -Extend the abstraction to include specific shapes.
44 | * Implementation (Renderer Interface):
45 | -Represents the interface for payment gateways like PayPal or Stripe.
46 | * Concrete Implementations (VectorRenderer, RasterRenderer):
47 | -Implement rendering logic for vector graphics and raster graphics, respectively.
48 | * Client Code:
49 | -Works with any combination of shapes and renderers.
--------------------------------------------------------------------------------
/patterns/Behavioral/Command/JavaScript/RealWorldExample/DocumentProcessing.js:
--------------------------------------------------------------------------------
1 | class Command {
2 | execute() {}
3 | getId() {}
4 | getStatus() {}
5 | }
6 |
7 | class DocumentCommand extends Command {
8 | constructor(document) {
9 | super();
10 | this.id = null;
11 | this.status = 0;
12 | this.document = document;
13 | }
14 |
15 | getId() {
16 | return this.id;
17 | }
18 |
19 | getStatus() {
20 | return this.status;
21 | }
22 |
23 | getDocument() {
24 | return this.document;
25 | }
26 |
27 | execute() {
28 | this.process();
29 | this.complete();
30 | }
31 |
32 | process() {
33 | throw new Error("Method 'process()' must be implemented.");
34 | }
35 |
36 | complete() {
37 | this.status = 1;
38 | Queue.get().completeCommand(this);
39 | }
40 | }
41 |
42 | class PrintDocumentCommand extends DocumentCommand {
43 | process() {
44 | console.log(`PrintDocumentCommand: Printing document '${this.document}'.`);
45 | }
46 | }
47 |
48 | class SaveDocumentCommand extends DocumentCommand {
49 | process() {
50 | console.log(`SaveDocumentCommand: Saving document '${this.document}'.`);
51 | }
52 | }
53 |
54 | class ConvertDocumentCommand extends DocumentCommand {
55 | process() {
56 | console.log(`ConvertDocumentCommand: Converting document '${this.document}'.`);
57 | }
58 | }
59 |
60 | class Queue {
61 | constructor() {
62 | this.db = new Map();
63 | this.lastId = 0;
64 | }
65 |
66 | isEmpty() {
67 | for (let [key, value] of this.db) {
68 | if (value.status === 0) {
69 | return false;
70 | }
71 | }
72 | return true;
73 | }
74 |
75 | add(command) {
76 | this.lastId++;
77 | command.id = this.lastId;
78 | this.db.set(this.lastId, { command: command, status: command.getStatus() });
79 | }
80 |
81 | getCommand() {
82 | for (let [key, value] of this.db) {
83 | if (value.status === 0) {
84 | return value.command;
85 | }
86 | }
87 | return null;
88 | }
89 |
90 | completeCommand(command) {
91 | if (this.db.has(command.getId())) {
92 | this.db.get(command.getId()).status = command.getStatus();
93 | }
94 | }
95 |
96 | work() {
97 | while (!this.isEmpty()) {
98 | const command = this.getCommand();
99 | if (command === null) {
100 | break;
101 | }
102 | command.execute();
103 | }
104 | }
105 |
106 | static get() {
107 | if (!Queue.instance) {
108 | Queue.instance = new Queue();
109 | }
110 | return Queue.instance;
111 | }
112 | }
113 |
114 | // Client Code
115 | const queue = Queue.get();
116 |
117 | // Adding commands to the queue
118 | if (queue.isEmpty()) {
119 | queue.add(new PrintDocumentCommand("Document1.pdf"));
120 | queue.add(new SaveDocumentCommand("Document1.pdf"));
121 | queue.add(new ConvertDocumentCommand("Document1.pdf"));
122 | }
123 |
124 | // Processing the commands in the queue
125 | queue.work();
126 |
--------------------------------------------------------------------------------
/patterns/Structural/Proxy/PHP/RealWorldExample/Downloader.php:
--------------------------------------------------------------------------------
1 | downloader = $downloader;
58 | }
59 |
60 | public function download(string $url): string
61 | {
62 | if (!isset($this->cache[$url])) {
63 | echo "CacheProxy MISS. ";
64 | $result = $this->downloader->download($url);
65 | $this->cache[$url] = $result;
66 | } else {
67 | echo "CacheProxy HIT. Retrieving result from cache.\n";
68 | }
69 | return $this->cache[$url];
70 | }
71 | }
72 |
73 | /**
74 | * The client code may issue several similar download requests. In this case,
75 | * the caching proxy saves time and traffic by serving results from cache.
76 | *
77 | * The client is unaware that it works with a proxy because it works with
78 | * downloaders via the abstract interface.
79 | */
80 | function clientCode(Downloader $subject)
81 | {
82 | // ...
83 |
84 | $result = $subject->download("http://example.com/");
85 |
86 | // Duplicate download requests could be cached for a speed gain.
87 |
88 | $result = $subject->download("http://example.com/");
89 |
90 | // ...
91 | }
92 |
93 | echo "Executing client code with real subject:\n";
94 | $realSubject = new SimpleDownloader();
95 | clientCode($realSubject);
96 |
97 | echo "\n";
98 |
99 | echo "Executing the same client code with a proxy:\n";
100 | $proxy = new CachingDownloader($realSubject);
101 | clientCode($proxy);
--------------------------------------------------------------------------------
/patterns/Structural/Adapter/PHP/RealWorldExample/PayPalPayment.php:
--------------------------------------------------------------------------------
1 | email = $email;
54 | $this->password = $password;
55 | }
56 |
57 | public function login(): void
58 | {
59 | echo "Logged in to PayPal account '{$this->email}'.\n";
60 | }
61 |
62 | public function makePayment(int $amount): void
63 | {
64 | echo "PayPal processing payment of $$amount.\n";
65 | }
66 | }
67 |
68 | /**
69 | * The Adapter class makes PayPalPayment compatible with the PaymentProcessor
70 | * interface.
71 | */
72 | class PayPalPaymentAdapter implements PaymentProcessor
73 | {
74 | private $payPalPayment;
75 |
76 | public function __construct(PayPalPayment $payPalPayment)
77 | {
78 | $this->payPalPayment = $payPalPayment;
79 | }
80 |
81 | public function pay(int $amount): void
82 | {
83 | $this->payPalPayment->login();
84 | $this->payPalPayment->makePayment($amount);
85 | }
86 | }
87 |
88 | /**
89 | * Client code that works with any class implementing the PaymentProcessor
90 | * interface.
91 | */
92 | function clientCode(PaymentProcessor $paymentProcessor)
93 | {
94 | // The client code can process a payment without knowing the exact class type
95 | $paymentProcessor->pay(100);
96 | }
97 |
98 | echo "Using CreditCardPayment:\n";
99 | $creditCardPayment = new CreditCardPayment();
100 | clientCode($creditCardPayment);
101 |
102 | echo "\n\nUsing PayPalPayment with Adapter:\n";
103 | $payPalPayment = new PayPalPayment("user@example.com", "securepassword");
104 | $payPalAdapter = new PayPalPaymentAdapter($payPalPayment);
105 | clientCode($payPalAdapter);
106 |
--------------------------------------------------------------------------------
/patterns/Creational/Prototype/PHP/RealWorldExamples/ComplexPage.php:
--------------------------------------------------------------------------------
1 | title = $title;
47 | $this->body = $body;
48 | $this->author = $author;
49 | $this->author->addToPage($this);
50 | $this->date = new \DateTime();
51 | }
52 |
53 | public function addComment(string $comment): void
54 | {
55 | $this->comments[] = $comment;
56 | }
57 |
58 | /**
59 | * You can control what data you want to carry over to the cloned object.
60 | *
61 | * For instance, when a page is cloned:
62 | * - It gets a new "Copy of ..." title.
63 | * - The author of the page remains the same. Therefore we leave the
64 | * reference to the existing object while adding the cloned page to the list
65 | * of the author's pages.
66 | * - We don't carry over the comments from the old page.
67 | * - We also attach a new date object to the page.
68 | */
69 | public function __clone()
70 | {
71 | $this->title = "Copy of " . $this->title;
72 | $this->author->addToPage($this);
73 | $this->comments = [];
74 | $this->date = new \DateTime();
75 | }
76 | }
77 |
78 | class Author
79 | {
80 | private $name;
81 |
82 | /**
83 | * @var Page[]
84 | */
85 | private $pages = [];
86 |
87 | public function __construct(string $name)
88 | {
89 | $this->name = $name;
90 | }
91 |
92 | public function addToPage(Page $page): void
93 | {
94 | $this->pages[] = $page;
95 | }
96 | }
97 |
98 | /**
99 | * The client code.
100 | */
101 | function clientCode()
102 | {
103 | $author = new Author("John Smith");
104 | $page = new Page("Tip of the day", "Keep calm and carry on.", $author);
105 |
106 | // ...
107 |
108 | $page->addComment("Nice tip, thanks!");
109 |
110 | // ...
111 |
112 | $draft = clone $page;
113 | echo "Dump of the clone. Note that the author is now referencing two objects.\n\n";
114 | print_r($draft);
115 | }
116 |
117 | clientCode();
118 |
--------------------------------------------------------------------------------
/patterns/Structural/Bridge/PHP/RealWorldExample/PaymentSystem.php:
--------------------------------------------------------------------------------
1 | gateway = $gateway;
34 | }
35 |
36 | abstract public function pay(float $amount): string;
37 | }
38 |
39 | /**
40 | * Refined Abstraction: Handles online payments.
41 | */
42 | class OnlinePayment extends Payment
43 | {
44 | public function pay(float $amount): string
45 | {
46 | return "OnlinePayment: Initiating online payment...\n" .
47 | $this->gateway->processPayment($amount);
48 | }
49 | }
50 |
51 | /**
52 | * Refined Abstraction: Handles in-store payments.
53 | */
54 | class InStorePayment extends Payment
55 | {
56 | public function pay(float $amount): string
57 | {
58 | return "InStorePayment: Initiating in-store payment...\n" .
59 | $this->gateway->processPayment($amount);
60 | }
61 | }
62 |
63 | /**
64 | * The Implementation defines the interface for payment gateways.
65 | */
66 | interface PaymentGateway
67 | {
68 | public function processPayment(float $amount): string;
69 | }
70 |
71 | /**
72 | * Concrete Implementation: Handles payments through PayPal.
73 | */
74 | class PayPalGateway implements PaymentGateway
75 | {
76 | public function processPayment(float $amount): string
77 | {
78 | return "PayPalGateway: Processing payment of $$amount through PayPal.\n";
79 | }
80 | }
81 |
82 | /**
83 | * Concrete Implementation: Handles payments through Stripe.
84 | */
85 | class StripeGateway implements PaymentGateway
86 | {
87 | public function processPayment(float $amount): string
88 | {
89 | return "StripeGateway: Processing payment of $$amount through Stripe.\n";
90 | }
91 | }
92 |
93 | /**
94 | * Client Code
95 | */
96 | function clientCode(Payment $payment, float $amount)
97 | {
98 | echo $payment->pay($amount);
99 | }
100 |
101 | // Client: Testing Online Payment with PayPal
102 | $paypalGateway = new PayPalGateway();
103 | $onlinePayment = new OnlinePayment($paypalGateway);
104 | clientCode($onlinePayment, 100.00);
105 |
106 | echo "\n\n";
107 |
108 | // Client: Testing In-Store Payment with Stripe
109 | $stripeGateway = new StripeGateway();
110 | $inStorePayment = new InStorePayment($stripeGateway);
111 | clientCode($inStorePayment, 250.50);
112 |
--------------------------------------------------------------------------------
/patterns/Creational/FactoryMethod/JavaScript/FactoryMethod.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Factory Method Design Pattern - Implementation Example
3 | *
4 | * This example demonstrates the Factory Method Design Pattern, which defines
5 | * an interface for creating an object but allows subclasses to alter the type
6 | * of objects that will be created.
7 | *
8 | * Key Components:
9 | * 1. Creator (Abstract Class): Declares the factory method that returns Product objects.
10 | * It may contain core business logic that relies on the Product objects.
11 | * 2. Concrete Creators: Override the factory method to create specific ConcreteProduct instances.
12 | * 3. Product (Interface): Defines the common interface that all products must implement.
13 | * 4. Concrete Products: Implement the Product interface, providing different implementations of the `operation` method.
14 | * 5. Client Code: Works with the Creator and Product via their abstract interfaces, ensuring flexibility and decoupling.
15 | *
16 | * Use Case:
17 | * Use the Factory Method pattern when a class cannot anticipate the type of objects
18 | * it must create or when a class wants its subclasses to specify the objects it creates.
19 | */
20 |
21 | // Abstract Creator
22 | class Creator {
23 | /**
24 | * The factory method, which must be implemented by subclasses.
25 | */
26 | factoryMethod() {
27 | throw new Error("You must override this method in a subclass.");
28 | }
29 |
30 | /**
31 | * Contains business logic that relies on Product objects created by the factory method.
32 | */
33 | someOperation() {
34 | // Call the factory method to create a Product object.
35 | const product = this.factoryMethod();
36 |
37 | // Use the product.
38 | return `Creator: The same creator's code has just worked with ${product.operation()}`;
39 | }
40 | }
41 |
42 | // Concrete Creator 1
43 | class ConcreteCreator1 extends Creator {
44 | /**
45 | * Overrides the factory method to create a specific product.
46 | */
47 | factoryMethod() {
48 | return new ConcreteProduct1();
49 | }
50 | }
51 |
52 | // Concrete Creator 2
53 | class ConcreteCreator2 extends Creator {
54 | /**
55 | * Overrides the factory method to create a specific product.
56 | */
57 | factoryMethod() {
58 | return new ConcreteProduct2();
59 | }
60 | }
61 |
62 | // Abstract Product
63 | class Product {
64 | /**
65 | * The operation method that all concrete products must implement.
66 | */
67 | operation() {
68 | throw new Error("You must override this method in a subclass.");
69 | }
70 | }
71 |
72 | // Concrete Product 1
73 | class ConcreteProduct1 extends Product {
74 | operation() {
75 | return "{Result of the ConcreteProduct1}";
76 | }
77 | }
78 |
79 | // Concrete Product 2
80 | class ConcreteProduct2 extends Product {
81 | operation() {
82 | return "{Result of the ConcreteProduct2}";
83 | }
84 | }
85 |
86 | // Client Code
87 | function clientCode(creator) {
88 | console.log(`Client: I'm not aware of the creator's class, but it still works.\n${creator.someOperation()}`);
89 | }
90 |
91 | // Application
92 | console.log("App: Launched with the ConcreteCreator1.");
93 | clientCode(new ConcreteCreator1());
94 | console.log("\n");
95 |
96 | console.log("App: Launched with the ConcreteCreator2.");
97 | clientCode(new ConcreteCreator2());
98 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/JavaScript/AbstractFactory.js:
--------------------------------------------------------------------------------
1 | // AbstractFactory.js - Abstract Factory Interface
2 | class AbstractFactory {
3 | createProductA() {
4 | throw new Error("Method 'createProductA()' must be implemented.");
5 | }
6 |
7 | createProductB() {
8 | throw new Error("Method 'createProductB()' must be implemented.");
9 | }
10 | }
11 |
12 | // ConcreteFactory1.js - Concrete Factory 1
13 | class ConcreteFactory1 extends AbstractFactory {
14 | createProductA() {
15 | return new ConcreteProductA1();
16 | }
17 |
18 | createProductB() {
19 | return new ConcreteProductB1();
20 | }
21 | }
22 |
23 | // ConcreteFactory2.js - Concrete Factory 2
24 | class ConcreteFactory2 extends AbstractFactory {
25 | createProductA() {
26 | return new ConcreteProductA2();
27 | }
28 |
29 | createProductB() {
30 | return new ConcreteProductB2();
31 | }
32 | }
33 |
34 | // AbstractProductA.js - Abstract Product A Interface
35 | class AbstractProductA {
36 | usefulFunctionA() {
37 | throw new Error("Method 'usefulFunctionA()' must be implemented.");
38 | }
39 | }
40 |
41 | // ConcreteProductA1.js - Concrete Product A1
42 | class ConcreteProductA1 extends AbstractProductA {
43 | usefulFunctionA() {
44 | return "The result of the product A1.";
45 | }
46 | }
47 |
48 | // ConcreteProductA2.js - Concrete Product A2
49 | class ConcreteProductA2 extends AbstractProductA {
50 | usefulFunctionA() {
51 | return "The result of the product A2.";
52 | }
53 | }
54 |
55 | // AbstractProductB.js - Abstract Product B Interface
56 | class AbstractProductB {
57 | usefulFunctionB() {
58 | throw new Error("Method 'usefulFunctionB()' must be implemented.");
59 | }
60 |
61 | anotherUsefulFunctionB(collaborator) {
62 | throw new Error("Method 'anotherUsefulFunctionB()' must be implemented.");
63 | }
64 | }
65 |
66 | // ConcreteProductB1.js - Concrete Product B1
67 | class ConcreteProductB1 extends AbstractProductB {
68 | usefulFunctionB() {
69 | return "The result of the product B1.";
70 | }
71 |
72 | anotherUsefulFunctionB(collaborator) {
73 | const result = collaborator.usefulFunctionA();
74 | return `The result of the B1 collaborating with the (${result})`;
75 | }
76 | }
77 |
78 | // ConcreteProductB2.js - Concrete Product B2
79 | class ConcreteProductB2 extends AbstractProductB {
80 | usefulFunctionB() {
81 | return "The result of the product B2.";
82 | }
83 |
84 | anotherUsefulFunctionB(collaborator) {
85 | const result = collaborator.usefulFunctionA();
86 | return `The result of the B2 collaborating with the (${result})`;
87 | }
88 | }
89 |
90 | // Client.js - Client Code
91 | function clientCode(factory) {
92 | const productA = factory.createProductA();
93 | const productB = factory.createProductB();
94 |
95 | console.log(productB.usefulFunctionB());
96 | console.log(productB.anotherUsefulFunctionB(productA));
97 | }
98 |
99 | // Usage
100 | console.log("Client: Testing client code with the first factory type:");
101 | clientCode(new ConcreteFactory1());
102 |
103 | console.log("\nClient: Testing the same client code with the second factory type:");
104 | clientCode(new ConcreteFactory2());
105 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Command/JavaScript/RealWorldExample/HomeAutomation.js:
--------------------------------------------------------------------------------
1 | class Command {
2 | execute() {}
3 | undo() {}
4 | }
5 |
6 | class Light {
7 | turnOn() {
8 | console.log("Light: Turned on");
9 | }
10 |
11 | turnOff() {
12 | console.log("Light: Turned off");
13 | }
14 | }
15 |
16 | class Thermostat {
17 | setTemperature(temperature) {
18 | console.log(`Thermostat: Set temperature to ${temperature}°C`);
19 | }
20 |
21 | reset() {
22 | console.log("Thermostat: Reset to default temperature");
23 | }
24 | }
25 |
26 | class SecuritySystem {
27 | activate() {
28 | console.log("SecuritySystem: Activated");
29 | }
30 |
31 | deactivate() {
32 | console.log("SecuritySystem: Deactivated");
33 | }
34 | }
35 |
36 | class LightOnCommand extends Command {
37 | constructor(light) {
38 | super();
39 | this.light = light;
40 | }
41 |
42 | execute() {
43 | this.light.turnOn();
44 | }
45 |
46 | undo() {
47 | this.light.turnOff();
48 | }
49 | }
50 |
51 | class ThermostatSetCommand extends Command {
52 | constructor(thermostat, temperature) {
53 | super();
54 | this.thermostat = thermostat;
55 | this.temperature = temperature;
56 | }
57 |
58 | execute() {
59 | this.thermostat.setTemperature(this.temperature);
60 | }
61 |
62 | undo() {
63 | this.thermostat.reset();
64 | }
65 | }
66 |
67 | class SecuritySystemActivateCommand extends Command {
68 | constructor(securitySystem) {
69 | super();
70 | this.securitySystem = securitySystem;
71 | }
72 |
73 | execute() {
74 | this.securitySystem.activate();
75 | }
76 |
77 | undo() {
78 | this.securitySystem.deactivate();
79 | }
80 | }
81 |
82 | class HomeAutomationController {
83 | constructor() {
84 | this.commandHistory = [];
85 | }
86 |
87 | executeCommand(command) {
88 | command.execute();
89 | this.commandHistory.push(command);
90 | }
91 |
92 | undoLastCommand() {
93 | if (this.commandHistory.length > 0) {
94 | const command = this.commandHistory.pop();
95 | command.undo();
96 | }
97 | }
98 | }
99 |
100 | // Client Code
101 | const light = new Light();
102 | const thermostat = new Thermostat();
103 | const securitySystem = new SecuritySystem();
104 |
105 | const lightOn = new LightOnCommand(light);
106 | const thermostatSet = new ThermostatSetCommand(thermostat, 22);
107 | const securityActivate = new SecuritySystemActivateCommand(securitySystem);
108 |
109 | const controller = new HomeAutomationController();
110 |
111 | // Execute commands
112 | controller.executeCommand(lightOn); // Turn on the light
113 | controller.executeCommand(thermostatSet); // Set thermostat to 22°C
114 | controller.executeCommand(securityActivate); // Activate security system
115 |
116 | console.log("\n--- Undo Last Command ---\n");
117 |
118 | // Undo the last command (deactivate security system)
119 | controller.undoLastCommand();
120 |
121 | console.log("\n--- Undo Another Command ---\n");
122 |
123 | // Undo the second last command (reset thermostat)
124 | controller.undoLastCommand();
125 |
126 | console.log("\n--- Undo Last Command ---\n");
127 |
128 | // Undo the last command (turn off the light)
129 | controller.undoLastCommand();
130 |
--------------------------------------------------------------------------------
/patterns/Structural/Adapter/README.md:
--------------------------------------------------------------------------------
1 | Adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.
2 |
3 | The Adapter acts as a wrapper between two objects. It catches calls for one object and transforms them to format and interface recognizable by the second object.
4 |
5 | # Conceptual Example:
6 | This example illustrates the structure of the Adapter design pattern and focuses on the following questions:
7 | * What classes does it consist of?
8 | * What roles do these classes play?
9 | * In what way the elements of the pattern are related?
10 |
11 | After learning about the pattern’s structure it’ll be easier for you to grasp the following example, based on a real-world PHP, Go, Js and Java use case.
12 |
13 | # Real World Example:
14 | ## Notification
15 | The Adapter pattern allows you to use 3rd-party or legacy classes even if they’re incompatible with the bulk of your code. For example, instead of rewriting the notification interface of your app to support each 3rd-party service such as Slack, Facebook, SMS or (you-name-it), you can create a set of special wrappers that adapt calls from your app to an interface and format required by each 3rd-party class.
16 |
17 | ## PayPalPayment
18 | Adapter Design Pattern where we integrate a third-party PayPal payment service with an existing credit card payment interface. This example demonstrates how the adapter pattern can help integrate incompatible interfaces for payment processing in a unified way.
19 |
20 | ### Explanation:
21 | * Target Interface (PaymentProcessor): This interface requires a pay method, allowing the client code to process payments consistently.
22 | * Existing Class (CreditCardPayment): A class that processes credit card payments by directly implementing the PaymentProcessor interface.
23 | * Adaptee Class (PayPalPayment): Represents a third-party PayPal payment service that doesn’t implement PaymentProcessor and has different methods (login and makePayment).
24 | * Adapter Class (PayPalPaymentAdapter): Adapts PayPalPayment to be compatible with PaymentProcessor by implementing the pay method, which uses login and makePayment internally.
25 | * Client Code: Can handle any PaymentProcessor implementation, meaning it can use both CreditCardPayment and PayPalPaymentAdapter seamlessly.
26 |
27 | ## CurrencyConverter:
28 | Adapter design pattern, which demonstrates integrating a third-party currency conversion system (CurrencyConverterAPI) with a standard currency calculation interface. This approach allows the application to convert prices across various currencies seamlessly.
29 | ### Explanation:
30 | * Target Interface (CurrencyCalculator): defines a convert method to standardize currency conversion.
31 | * Existing Class (SimpleCurrencyConverter): performs currency conversion with a fixed rate, already adhering to the interface.
32 | * Adaptee (CurrencyConverterAPI): a third-party API for currency conversion that has an incompatible interface with the target. It uses getConvertedAmount with different parameters.
33 | * Adapter (CurrencyConverterAPIAdapter): makes the API compatible with CurrencyCalculator, adapting the convert call to getConvertedAmount.
34 | * Client Code: can convert currencies without knowing the source, using either simple conversion or the third-party API through the adapter.
35 |
36 | This examples demonstrate how the Adapter pattern allows integrating an external conversion API into a standardized interface, letting the client code interact with multiple currency providers without modification.
--------------------------------------------------------------------------------
/patterns/Creational/Builder/Go/RealWorldExample/SQLQueryBuilder.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | )
7 |
8 | // Builder Design Pattern - SQL Query Builder
9 | //
10 | // This example demonstrates the Factory Method Design Pattern to send various
11 | // types of notifications (Email, SMS).
12 |
13 | // SQLQueryBuilder interface declares a set of methods to assemble an SQL query.
14 | type SQLQueryBuilder interface {
15 | Select(table string, fields []string) SQLQueryBuilder
16 | Where(field string, value string, operator string) SQLQueryBuilder
17 | Limit(start int, offset int) SQLQueryBuilder
18 | GetSQL() string
19 | }
20 |
21 | // Concrete Builder for MySQL SQL queries.
22 | type MysqlQueryBuilder struct {
23 | query *SQLQuery
24 | }
25 |
26 | func (b *MysqlQueryBuilder) reset() {
27 | b.query = &SQLQuery{}
28 | }
29 |
30 | func (b *MysqlQueryBuilder) Select(table string, fields []string) SQLQueryBuilder {
31 | b.reset()
32 | b.query.base = fmt.Sprintf("SELECT %s FROM %s", strings.Join(fields, ", "), table)
33 | b.query.queryType = "select"
34 | return b
35 | }
36 |
37 | func (b *MysqlQueryBuilder) Where(field string, value string, operator string) SQLQueryBuilder {
38 | if b.query.queryType != "select" && b.query.queryType != "update" && b.query.queryType != "delete" {
39 | panic("WHERE can only be added to SELECT, UPDATE OR DELETE")
40 | }
41 | b.query.where = append(b.query.where, fmt.Sprintf("%s %s '%s'", field, operator, value))
42 | return b
43 | }
44 |
45 | func (b *MysqlQueryBuilder) Limit(start int, offset int) SQLQueryBuilder {
46 | if b.query.queryType != "select" {
47 | panic("LIMIT can only be added to SELECT")
48 | }
49 | b.query.limit = fmt.Sprintf(" LIMIT %d, %d", start, offset)
50 | return b
51 | }
52 |
53 | func (b *MysqlQueryBuilder) GetSQL() string {
54 | sql := b.query.base
55 | if len(b.query.where) > 0 {
56 | sql += " WHERE " + strings.Join(b.query.where, " AND ")
57 | }
58 | if b.query.limit != "" {
59 | sql += b.query.limit
60 | }
61 | return sql + ";"
62 | }
63 |
64 | // Concrete Builder for PostgreSQL SQL queries.
65 | type PostgresQueryBuilder struct {
66 | MysqlQueryBuilder
67 | }
68 |
69 | func (b *PostgresQueryBuilder) Limit(start int, offset int) SQLQueryBuilder {
70 | b.MysqlQueryBuilder.Limit(start, offset)
71 | b.query.limit = fmt.Sprintf(" LIMIT %d OFFSET %d", start, offset)
72 | return b
73 | }
74 |
75 | // SQLQuery represents the SQL query being built.
76 | type SQLQuery struct {
77 | base string
78 | where []string
79 | limit string
80 | queryType string
81 | }
82 |
83 | // Client code to demonstrate the SQL Query Builder.
84 | func clientCode(builder SQLQueryBuilder) {
85 | query := builder.Select("users", []string{"name", "email", "password"}).
86 | Where("age", "18", ">").
87 | Where("age", "30", "<").
88 | Limit(10, 20).
89 | GetSQL()
90 |
91 | fmt.Println(query)
92 | }
93 |
94 | func main() {
95 | fmt.Println("Testing MySQL query builder:")
96 | clientCode(&MysqlQueryBuilder{})
97 | fmt.Println()
98 |
99 | fmt.Println("Testing PostgreSQL query builder:")
100 | clientCode(&PostgresQueryBuilder{})
101 | fmt.Println()
102 | }
103 |
--------------------------------------------------------------------------------
/patterns/Creational/FactoryMethod/Go/FactoryMethod.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | /*
8 | |--------------------------------------------------------------------------
9 | | Factory Method Design Pattern - Implementation Example
10 | |--------------------------------------------------------------------------
11 | | This example demonstrates the Factory Method Design Pattern, which defines
12 | | an interface for creating an object but allows subclasses to alter the type
13 | | of objects that will be created.
14 | |--------------------------------------------------------------------------
15 | | Key Components:
16 | | 1. Creator (Abstract Class): Declares the factory method that returns
17 | | Product objects. It may contain core business logic that relies on the
18 | | Product objects.
19 | | 2. Concrete Creators: Override the factory method to create specific
20 | | ConcreteProduct instances.
21 | | 3. Product (Interface): Defines the common interface that all products must
22 | | implement.
23 | | 4. Concrete Products: Implement the Product interface, providing different
24 | | implementations of the `operation` method.
25 | | 5. Client Code: Works with the Creator and Product via their abstract
26 | | interfaces, ensuring flexibility and decoupling.
27 | |--------------------------------------------------------------------------
28 | | Use Case:
29 | | Use the Factory Method pattern when a class cannot anticipate the type of
30 | | objects it must create or when a class wants its subclasses to specify the
31 | | objects it creates.
32 | */
33 |
34 | type Product interface {
35 | Operation() string
36 | }
37 |
38 | // Creator declares the factory method.
39 | type Creator interface {
40 | FactoryMethod() Product
41 | SomeOperation() string
42 | }
43 |
44 | // ConcreteCreator1 implements the Creator and overrides the FactoryMethod.
45 | type ConcreteCreator1 struct{}
46 |
47 | func (c *ConcreteCreator1) FactoryMethod() Product {
48 | return &ConcreteProduct1{}
49 | }
50 |
51 | func (c *ConcreteCreator1) SomeOperation() string {
52 | product := c.FactoryMethod()
53 | return "Creator: The same creator's code has just worked with " + product.Operation()
54 | }
55 |
56 | // ConcreteCreator2 implements the Creator and overrides the FactoryMethod.
57 | type ConcreteCreator2 struct{}
58 |
59 | func (c *ConcreteCreator2) FactoryMethod() Product {
60 | return &ConcreteProduct2{}
61 | }
62 |
63 | func (c *ConcreteCreator2) SomeOperation() string {
64 | product := c.FactoryMethod()
65 | return "Creator: The same creator's code has just worked with " + product.Operation()
66 | }
67 |
68 | // ConcreteProduct1 implements the Product interface.
69 | type ConcreteProduct1 struct{}
70 |
71 | func (p *ConcreteProduct1) Operation() string {
72 | return "{Result of the ConcreteProduct1}"
73 | }
74 |
75 | // ConcreteProduct2 implements the Product interface.
76 | type ConcreteProduct2 struct{}
77 |
78 | func (p *ConcreteProduct2) Operation() string {
79 | return "{Result of the ConcreteProduct2}"
80 | }
81 |
82 | // Client code.
83 | func clientCode(creator Creator) {
84 | fmt.Println("Client: I'm not aware of the creator's class, but it still works.")
85 | fmt.Println(creator.SomeOperation())
86 | }
87 |
88 | func main() {
89 | // Application picks a creator's type depending on the configuration or environment.
90 | fmt.Println("App: Launched with the ConcreteCreator1.")
91 | clientCode(&ConcreteCreator1{})
92 |
93 | fmt.Println("\nApp: Launched with the ConcreteCreator2.")
94 | clientCode(&ConcreteCreator2{})
95 | }
96 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Command/Go/RealWorldExample/HomeAutomation.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // Command interface
6 | type Command interface {
7 | Execute()
8 | Undo()
9 | }
10 |
11 | // Receiver: Smart Light
12 | type Light struct{}
13 |
14 | func (l *Light) TurnOn() {
15 | fmt.Println("Light: Turned on")
16 | }
17 |
18 | func (l *Light) TurnOff() {
19 | fmt.Println("Light: Turned off")
20 | }
21 |
22 | // Receiver: Thermostat
23 | type Thermostat struct{}
24 |
25 | func (t *Thermostat) SetTemperature(temp int) {
26 | fmt.Printf("Thermostat: Set temperature to %d°C\n", temp)
27 | }
28 |
29 | func (t *Thermostat) Reset() {
30 | fmt.Println("Thermostat: Reset to default temperature")
31 | }
32 |
33 | // Receiver: Security System
34 | type SecuritySystem struct{}
35 |
36 | func (s *SecuritySystem) Activate() {
37 | fmt.Println("SecuritySystem: Activated")
38 | }
39 |
40 | func (s *SecuritySystem) Deactivate() {
41 | fmt.Println("SecuritySystem: Deactivated")
42 | }
43 |
44 | // Concrete Command: Light On Command
45 | type LightOnCommand struct {
46 | light *Light
47 | }
48 |
49 | func (c *LightOnCommand) Execute() {
50 | c.light.TurnOn()
51 | }
52 |
53 | func (c *LightOnCommand) Undo() {
54 | c.light.TurnOff()
55 | }
56 |
57 | // Concrete Command: Thermostat Set Command
58 | type ThermostatSetCommand struct {
59 | thermostat *Thermostat
60 | temperature int
61 | }
62 |
63 | func (c *ThermostatSetCommand) Execute() {
64 | c.thermostat.SetTemperature(c.temperature)
65 | }
66 |
67 | func (c *ThermostatSetCommand) Undo() {
68 | c.thermostat.Reset()
69 | }
70 |
71 | // Concrete Command: Security System Activate Command
72 | type SecuritySystemActivateCommand struct {
73 | securitySystem *SecuritySystem
74 | }
75 |
76 | func (c *SecuritySystemActivateCommand) Execute() {
77 | c.securitySystem.Activate()
78 | }
79 |
80 | func (c *SecuritySystemActivateCommand) Undo() {
81 | c.securitySystem.Deactivate()
82 | }
83 |
84 | // Invoker: Home Automation Controller
85 | type HomeAutomationController struct {
86 | commandHistory []Command
87 | }
88 |
89 | func (h *HomeAutomationController) ExecuteCommand(cmd Command) {
90 | cmd.Execute()
91 | h.commandHistory = append(h.commandHistory, cmd)
92 | }
93 |
94 | func (h *HomeAutomationController) UndoLastCommand() {
95 | if len(h.commandHistory) > 0 {
96 | lastCmd := h.commandHistory[len(h.commandHistory)-1]
97 | h.commandHistory = h.commandHistory[:len(h.commandHistory)-1]
98 | lastCmd.Undo()
99 | }
100 | }
101 |
102 | func main() {
103 | // Receivers
104 | light := &Light{}
105 | thermostat := &Thermostat{}
106 | securitySystem := &SecuritySystem{}
107 |
108 | // Commands
109 | lightOn := &LightOnCommand{light}
110 | thermostatSet := &ThermostatSetCommand{thermostat, 22}
111 | securityActivate := &SecuritySystemActivateCommand{securitySystem}
112 |
113 | // Invoker
114 | controller := &HomeAutomationController{}
115 |
116 | // Execute commands
117 | controller.ExecuteCommand(lightOn)
118 | controller.ExecuteCommand(thermostatSet)
119 | controller.ExecuteCommand(securityActivate)
120 |
121 | fmt.Println("\n--- Undo Last Command ---")
122 | controller.UndoLastCommand()
123 |
124 | fmt.Println("\n--- Undo Another Command ---")
125 | controller.UndoLastCommand()
126 |
127 | fmt.Println("\n--- Undo Last Command ---")
128 | controller.UndoLastCommand()
129 | }
130 |
--------------------------------------------------------------------------------
/patterns/Creational/AbstractFactory/PHP/RealWorldExample/SystemUIComponents.php:
--------------------------------------------------------------------------------
1 | createButton();
129 | echo $button->render();
130 |
131 | $checkbox = $factory->createCheckbox();
132 | echo $checkbox->toggle();
133 | }
134 |
135 | echo "Testing Windows UI factory:\n";
136 | renderUI(new WindowsFactory());
137 | echo "\n\n";
138 |
139 | echo "Testing Mac UI factory:\n";
140 | renderUI(new MacFactory());
--------------------------------------------------------------------------------
/patterns/Creational/Prototype/Java/RealWorldExamples/Document.java:
--------------------------------------------------------------------------------
1 | package patterns.Creational.Prototype.Java.RealWorldExamples;
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | Prototype Design Pattern - Document Example
6 | |--------------------------------------------------------------------------
7 | | Implement the Prototype Design Pattern to create new instances by cloning
8 | | existing objects, which can avoid costly initialization steps.
9 | |--------------------------------------------------------------------------
10 | | @category Design Pattern
11 | | @package Creational.Prototype.RealWorldExamples
12 | | @version 1.0.0
13 | | @license MIT License
14 | | @link https://github.com/JawherKl/design-patterns-in-java
15 | |--------------------------------------------------------------------------
16 | */
17 |
18 | import java.util.ArrayList;
19 | import java.util.Date;
20 | import java.util.List;
21 |
22 | // Prototype Interface
23 | interface Prototype extends Cloneable {
24 | Prototype clone();
25 | }
26 |
27 | // Concrete Prototype: Document
28 | class Document implements Prototype {
29 | private String title;
30 | private String content;
31 | private Date createdAt;
32 | private Author author;
33 |
34 | public Document(String title, String content, Author author) {
35 | this.title = title;
36 | this.content = content;
37 | this.author = author;
38 | this.createdAt = new Date();
39 | this.author.addDocument(this);
40 | }
41 |
42 | @Override
43 | public Document clone() {
44 | try {
45 | Document clone = (Document) super.clone();
46 | clone.title = "Copy of " + this.title;
47 | clone.createdAt = new Date();
48 | this.author.addDocument(clone);
49 | return clone;
50 | } catch (CloneNotSupportedException e) {
51 | throw new AssertionError();
52 | }
53 | }
54 |
55 | public String getDetails() {
56 | return "Title: " + title + "\nContent: " + content + "\nAuthor: " + author.getName() + "\nCreatedAt: " + createdAt.toString();
57 | }
58 | }
59 |
60 | // The Author class, which has a collection of documents.
61 | class Author {
62 | private String name;
63 | private List documents = new ArrayList<>();
64 |
65 | public Author(String name) {
66 | this.name = name;
67 | }
68 |
69 | public String getName() {
70 | return name;
71 | }
72 |
73 | public void addDocument(Document document) {
74 | this.documents.add(document);
75 | }
76 |
77 | public List getDocuments() {
78 | return documents;
79 | }
80 | }
81 |
82 | // Client code that demonstrates the Prototype Design Pattern.
83 | public class Main {
84 | public static void main(String[] args) {
85 | // Create an author and a document.
86 | Author author = new Author("Jane Doe");
87 | Document originalDocument = new Document("Design Patterns", "Learning the Prototype Pattern.", author);
88 |
89 | // Clone the original document.
90 | Document clonedDocument = originalDocument.clone();
91 |
92 | // Display details of both documents.
93 | System.out.println("Original Document:");
94 | System.out.println(originalDocument.getDetails());
95 |
96 | System.out.println("\nCloned Document:");
97 | System.out.println(clonedDocument.getDetails());
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/patterns/Creational/Prototype/Go/RealWorldExamples/Shape.go:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Prototype Design Pattern - Shape Example
4 | |--------------------------------------------------------------------------
5 | | Implement the Prototype Design Pattern to clone shape objects,
6 | | avoiding the need for subclass-specific object creation processes.
7 | |--------------------------------------------------------------------------
8 | | @category Design Pattern
9 | | @package Creational/Prototype
10 | | @version 1.0.0
11 | | @license MIT License
12 | | @link https://github.com/JawherKl/design-patterns-in-go
13 | |--------------------------------------------------------------------------
14 | */
15 |
16 | package main
17 |
18 | import (
19 | "fmt"
20 | )
21 |
22 | // ShapePrototype interface defines the clone method.
23 | type ShapePrototype interface {
24 | Clone() ShapePrototype
25 | Draw() string
26 | SetColor(color string)
27 | }
28 |
29 | // Shape struct defines common properties and the cloning interface.
30 | type Shape struct {
31 | Color string
32 | }
33 |
34 | // SetColor sets the color of the shape.
35 | func (s *Shape) SetColor(color string) {
36 | s.Color = color
37 | }
38 |
39 | // Circle struct represents a concrete prototype.
40 | type Circle struct {
41 | Shape
42 | Radius int
43 | }
44 |
45 | // NewCircle is the constructor for Circle.
46 | func NewCircle(radius int) *Circle {
47 | return &Circle{Radius: radius}
48 | }
49 |
50 | // Draw outputs the properties of the circle.
51 | func (c *Circle) Draw() string {
52 | return fmt.Sprintf("Drawing a circle with radius %d and color %s", c.Radius, c.Color)
53 | }
54 |
55 | // Clone creates a copy of the circle.
56 | func (c *Circle) Clone() ShapePrototype {
57 | clone := *c
58 | return &clone
59 | }
60 |
61 | // Rectangle struct represents a concrete prototype.
62 | type Rectangle struct {
63 | Shape
64 | Width int
65 | Height int
66 | }
67 |
68 | // NewRectangle is the constructor for Rectangle.
69 | func NewRectangle(width, height int) *Rectangle {
70 | return &Rectangle{Width: width, Height: height}
71 | }
72 |
73 | // Draw outputs the properties of the rectangle.
74 | func (r *Rectangle) Draw() string {
75 | return fmt.Sprintf("Drawing a rectangle with width %d, height %d and color %s", r.Width, r.Height, r.Color)
76 | }
77 |
78 | // Clone creates a copy of the rectangle.
79 | func (r *Rectangle) Clone() ShapePrototype {
80 | clone := *r
81 | return &clone
82 | }
83 |
84 | // Client code demonstrating Prototype Design Pattern.
85 | func clientCode() {
86 | // Create a Circle object.
87 | circle := NewCircle(10)
88 | circle.SetColor("Red")
89 |
90 | // Clone the Circle object.
91 | clonedCircle := circle.Clone().(*Circle)
92 | clonedCircle.SetColor("Blue")
93 |
94 | // Create a Rectangle object.
95 | rectangle := NewRectangle(20, 10)
96 | rectangle.SetColor("Green")
97 |
98 | // Clone the Rectangle object.
99 | clonedRectangle := rectangle.Clone().(*Rectangle)
100 | clonedRectangle.SetColor("Yellow")
101 |
102 | // Output original and cloned shapes.
103 | fmt.Println("Original Circle: " + circle.Draw())
104 | fmt.Println("Cloned Circle: " + clonedCircle.Draw())
105 |
106 | fmt.Println("\nOriginal Rectangle: " + rectangle.Draw())
107 | fmt.Println("Cloned Rectangle: " + clonedRectangle.Draw())
108 | }
109 |
110 | func main() {
111 | clientCode()
112 | }
113 |
--------------------------------------------------------------------------------
/patterns/Creational/Prototype/JavaScript/RealWorldExamples/Document.js:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Prototype Design Pattern - Document Example
4 | |--------------------------------------------------------------------------
5 | | Implement the Prototype Design Pattern to create new instances by cloning
6 | | existing objects, which can avoid costly initialization steps.
7 | |--------------------------------------------------------------------------
8 | | @category Design Pattern
9 | | @package Creational/Prototype/RealWorldExamples
10 | | @version 1.0.0
11 | | @license MIT License
12 | | @link https://github.com/JawherKl/design-patterns-in-js
13 | |--------------------------------------------------------------------------
14 | */
15 |
16 | /**
17 | * Prototype Interface.
18 | * Defines the `clone` method that all prototypes must implement.
19 | */
20 | class Prototype {
21 | clone() {
22 | throw new Error("Method 'clone()' must be implemented.");
23 | }
24 | }
25 |
26 | /**
27 | * Concrete Prototype: Document
28 | */
29 | class Document extends Prototype {
30 | constructor(title, content, author) {
31 | super();
32 | this.title = title;
33 | this.content = content;
34 | this.author = author;
35 | this.createdAt = new Date();
36 | this.author.addDocument(this);
37 | }
38 |
39 | /**
40 | * Control what data to copy when cloning.
41 | * Example:
42 | * - The cloned document will have "Copy of ..." title.
43 | * - The author reference remains the same.
44 | * - The creation date is updated to the current date.
45 | */
46 | clone() {
47 | const clone = Object.create(Object.getPrototypeOf(this));
48 | clone.title = "Copy of " + this.title;
49 | clone.content = this.content;
50 | clone.author = this.author;
51 | clone.createdAt = new Date();
52 | // Add the cloned document to the author's list of documents.
53 | this.author.addDocument(clone);
54 | return clone;
55 | }
56 |
57 | getDetails() {
58 | return {
59 | Title: this.title,
60 | Content: this.content,
61 | Author: this.author.getName(),
62 | CreatedAt: this.createdAt.toISOString().slice(0, 19).replace('T', ' ')
63 | };
64 | }
65 | }
66 |
67 | /**
68 | * The Author class, which has a collection of documents.
69 | */
70 | class Author {
71 | constructor(name) {
72 | this.name = name;
73 | this.documents = [];
74 | }
75 |
76 | getName() {
77 | return this.name;
78 | }
79 |
80 | addDocument(document) {
81 | this.documents.push(document);
82 | }
83 |
84 | getDocuments() {
85 | return this.documents;
86 | }
87 | }
88 |
89 | /**
90 | * Client code that demonstrates the Prototype Design Pattern.
91 | */
92 | function clientCode() {
93 | // Create an author and a document.
94 | const author = new Author("Jane Doe");
95 | const originalDocument = new Document("Design Patterns", "Learning the Prototype Pattern.", author);
96 |
97 | // Clone the original document.
98 | const clonedDocument = originalDocument.clone();
99 |
100 | // Display details of both documents.
101 | console.log("Original Document:");
102 | console.log(originalDocument.getDetails());
103 |
104 | console.log("\nCloned Document:");
105 | console.log(clonedDocument.getDetails());
106 | }
107 |
108 | clientCode();
109 |
--------------------------------------------------------------------------------
/patterns/Behavioral/Command/Java/CommandExample.java:
--------------------------------------------------------------------------------
1 | /*
2 | |--------------------------------------------------------------------------
3 | | Command Design Pattern
4 | |--------------------------------------------------------------------------
5 | | This example demonstrates the Command Design Pattern
6 | |--------------------------------------------------------------------------
7 | | @category Design Pattern
8 | | @package Behavioral/Command
9 | | @version 1.0.0
10 | | @license MIT License
11 | | @link https://github.com/JawherKl/design-patterns-in-php
12 | |--------------------------------------------------------------------------
13 | */
14 |
15 | // Command interface declares a method for executing a command.
16 | interface Command {
17 | void execute();
18 | }
19 |
20 | // SimpleCommand implements the Command interface for simple operations.
21 | class SimpleCommand implements Command {
22 | private String payload;
23 |
24 | public SimpleCommand(String payload) {
25 | this.payload = payload;
26 | }
27 |
28 | @Override
29 | public void execute() {
30 | System.out.println("SimpleCommand: See, I can do simple things like printing (" + payload + ")");
31 | }
32 | }
33 |
34 | // ComplexCommand delegates more complex operations to a Receiver.
35 | class ComplexCommand implements Command {
36 | private Receiver receiver;
37 | private String a;
38 | private String b;
39 |
40 | public ComplexCommand(Receiver receiver, String a, String b) {
41 | this.receiver = receiver;
42 | this.a = a;
43 | this.b = b;
44 | }
45 |
46 | @Override
47 | public void execute() {
48 | System.out.println("ComplexCommand: Complex stuff should be done by a receiver object.");
49 | receiver.doSomething(a);
50 | receiver.doSomethingElse(b);
51 | }
52 | }
53 |
54 | // Receiver contains business logic and knows how to perform operations.
55 | class Receiver {
56 | public void doSomething(String a) {
57 | System.out.println("Receiver: Working on (" + a + ".)");
58 | }
59 |
60 | public void doSomethingElse(String b) {
61 | System.out.println("Receiver: Also working on (" + b + ".)");
62 | }
63 | }
64 |
65 | // Invoker is associated with commands and sends requests to them.
66 | class Invoker {
67 | private Command onStart;
68 | private Command onFinish;
69 |
70 | public void setOnStart(Command command) {
71 | this.onStart = command;
72 | }
73 |
74 | public void setOnFinish(Command command) {
75 | this.onFinish = command;
76 | }
77 |
78 | public void doSomethingImportant() {
79 | System.out.println("Invoker: Does anybody want something done before I begin?");
80 | if (onStart != null) {
81 | onStart.execute();
82 | }
83 |
84 | System.out.println("Invoker: ...doing something really important...");
85 |
86 | System.out.println("Invoker: Does anybody want something done after I finish?");
87 | if (onFinish != null) {
88 | onFinish.execute();
89 | }
90 | }
91 | }
92 |
93 | // Client code parameterizes an invoker with commands.
94 | public class CommandExample {
95 | public static void main(String[] args) {
96 | Invoker invoker = new Invoker();
97 | invoker.setOnStart(new SimpleCommand("Say Hi!"));
98 | Receiver receiver = new Receiver();
99 | invoker.setOnFinish(new ComplexCommand(receiver, "Send email", "Save report"));
100 |
101 | invoker.doSomethingImportant();
102 | }
103 | }
--------------------------------------------------------------------------------