├── tests ├── Go │ ├── decorator_test.go │ └── factory_method_test.go ├── PHP │ ├── DecoratorTest.php │ ├── .gitignore │ ├── composer.json │ └── FactoryMethodTest.php ├── Java │ ├── DecoratorTest.java │ └── FactoryMethodTest.java ├── JavaScript │ ├── DecoratorTest.js │ └── FactoryMethodTest.js └── README.md ├── patterns ├── Behavioral │ ├── State │ │ ├── README_fr.md │ │ ├── README.md │ │ └── PHP │ │ │ ├── RealWorldExample │ │ │ └── OrderProcess.php │ │ │ └── State.php │ ├── Command │ │ ├── README_fr.md │ │ ├── Go │ │ │ ├── RealWorldExample │ │ │ │ ├── commands.sqlite │ │ │ │ └── HomeAutomation.go │ │ │ └── Command.go │ │ ├── Java │ │ │ ├── RealWorldExample │ │ │ │ └── commands.sqlite │ │ │ └── CommandExample.java │ │ ├── PHP │ │ │ └── RealWorldExample │ │ │ │ └── commands.sqlite │ │ └── JavaScript │ │ │ ├── RealWorldExample │ │ │ ├── commands.sqlite │ │ │ ├── DocumentProcessing.js │ │ │ └── HomeAutomation.js │ │ │ └── Command.js │ ├── Iterator │ │ ├── README_fr.md │ │ ├── PHP │ │ │ ├── RealWorldExample │ │ │ │ ├── cats.csv │ │ │ │ ├── BookIterator.php │ │ │ │ └── UserIterator.php │ │ │ └── Iterator.php │ │ └── README.md │ ├── Mediator │ │ ├── README_fr.md │ │ ├── PHP │ │ │ ├── RealWorldExample │ │ │ │ └── log.txt │ │ │ └── Mediator.php │ │ └── README.md │ ├── Memento │ │ ├── README_fr.md │ │ └── PHP │ │ │ └── RealWorldExample │ │ │ └── TextEditor.php │ ├── Observer │ │ ├── README_fr.md │ │ └── PHP │ │ │ └── RealWorldExample │ │ │ └── log.txt │ ├── Strategy │ │ ├── README_fr.md │ │ └── README.md │ ├── Visitor │ │ ├── README_fr.md │ │ └── README.md │ ├── TemplateMethod │ │ ├── README_fr.md │ │ └── README.md │ └── ChainOfResponsibility │ │ └── README_fr.md ├── Creational │ ├── Builder │ │ ├── README_fr.md │ │ ├── JavaScript │ │ │ ├── Builder.js │ │ │ └── RealWorldExample │ │ │ │ └── SQLQueryBuilder.js │ │ ├── Go │ │ │ ├── Builder.go │ │ │ └── RealWorldExample │ │ │ │ └── SQLQueryBuilder.go │ │ └── README.md │ ├── Prototype │ │ ├── README_fr.md │ │ ├── JavaScript │ │ │ └── RealWorldExamples │ │ │ │ ├── ComplexPage.js │ │ │ │ └── Document.js │ │ ├── Go │ │ │ └── RealWorldExamples │ │ │ │ ├── ComplexPage.go │ │ │ │ └── Shape.go │ │ ├── README.md │ │ ├── PHP │ │ │ └── RealWorldExamples │ │ │ │ └── ComplexPage.php │ │ └── Java │ │ │ └── RealWorldExamples │ │ │ └── Document.java │ ├── Singleton │ │ ├── README_fr.md │ │ ├── Java │ │ │ ├── .gitignore │ │ │ └── RealWorldExample │ │ │ │ └── .gitignore │ │ ├── README.md │ │ ├── Go │ │ │ ├── Singleton.go │ │ │ └── RealWorldExamples │ │ │ │ ├── DatabaseConnection.go │ │ │ │ ├── CacheManager.go │ │ │ │ └── ApplicationSettings.go │ │ └── JavaScript │ │ │ ├── RealWorldExamples │ │ │ ├── CacheManager.js │ │ │ ├── DatabaseConnection.js │ │ │ └── ApplicationSettings.js │ │ │ └── Singleton.js │ ├── AbstractFactory │ │ ├── README_fr.md │ │ ├── Java │ │ │ ├── .gitignore │ │ │ └── RealWorldExample │ │ │ │ ├── ClientSystemUIComponents.java │ │ │ │ ├── ClientDatabaseFactory.java │ │ │ │ └── ClientNotificationFactory.java │ │ ├── README.md │ │ ├── Go │ │ │ ├── RealWorldExample │ │ │ │ ├── SystemUIComponents.go │ │ │ │ ├── DataBaseConnection.go │ │ │ │ └── NotificationServices.go │ │ │ └── AbstractFactory.go │ │ ├── JavaScript │ │ │ ├── RealWorldExample │ │ │ │ ├── SystemUIComponents.js │ │ │ │ ├── DataBaseConnection.js │ │ │ │ └── NotificationServices.js │ │ │ └── AbstractFactory.js │ │ └── PHP │ │ │ └── RealWorldExample │ │ │ └── SystemUIComponents.php │ └── FactoryMethod │ │ ├── README_fr.md │ │ ├── Java │ │ ├── .gitignore │ │ └── RealWorldExample │ │ │ └── .gitignore │ │ ├── README.md │ │ ├── JavaScript │ │ └── FactoryMethod.js │ │ └── Go │ │ └── FactoryMethod.go └── Structural │ ├── Flyweight │ ├── PHP │ │ └── RealWorldExample │ │ │ └── cats.csv │ ├── README.md │ └── README_fr.md │ ├── Decorator │ ├── README.md │ └── README_fr.md │ ├── Composite │ ├── README.md │ └── README_fr.md │ ├── Proxy │ ├── README.md │ ├── README_fr.md │ └── PHP │ │ └── RealWorldExample │ │ ├── Image.php │ │ └── Downloader.php │ ├── Facade │ ├── README.md │ ├── README_fr.md │ └── PHP │ │ └── RealWorldExample │ │ ├── MealOrder.php │ │ └── HomeAutomation.php │ ├── Adapter │ ├── PHP │ │ ├── Adapter.php │ │ └── RealWorldExample │ │ │ └── PayPalPayment.php │ └── README.md │ └── Bridge │ ├── README.md │ └── PHP │ └── RealWorldExample │ └── PaymentSystem.php ├── docs ├── design-patterns.jpeg ├── design-patterns.png ├── design-pattern-relationships.png └── UMLDiagrams │ ├── Creational │ ├── Singleton │ │ └── singleton.png │ └── FactoryMethod │ │ └── factory-notification-system.png │ └── Behavioral │ └── Strategy │ ├── strategy-structure.png │ └── strategy-payment-methods.png ├── .idea ├── vcs.xml ├── .gitignore ├── design-patterns-in-multiple-languages.iml ├── modules.xml ├── material_theme_project_new.xml └── php.xml ├── .github └── ISSUE_TEMPLATE │ ├── custom.md │ ├── feature_request.md │ └── bug_report.md ├── SECURITY.md ├── CONTRIBUTING.md └── LICENSE /tests/Go/decorator_test.go: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/PHP/DecoratorTest.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Java/DecoratorTest.java: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Java/FactoryMethodTest.java: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/JavaScript/DecoratorTest.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/PHP/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /patterns/Behavioral/State/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/Command/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/Iterator/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/Mediator/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/Memento/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/Observer/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/Strategy/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/Visitor/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Creational/Builder/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Creational/Prototype/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Creational/Singleton/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/TemplateMethod/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Creational/AbstractFactory/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Creational/FactoryMethod/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Behavioral/ChainOfResponsibility/README_fr.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /patterns/Creational/Singleton/Java/.gitignore: -------------------------------------------------------------------------------- 1 | /patterns/ 2 | -------------------------------------------------------------------------------- /patterns/Creational/AbstractFactory/Java/.gitignore: -------------------------------------------------------------------------------- 1 | /patterns/ 2 | -------------------------------------------------------------------------------- /patterns/Creational/FactoryMethod/Java/.gitignore: -------------------------------------------------------------------------------- 1 | /patterns/ 2 | -------------------------------------------------------------------------------- /patterns/Creational/Singleton/Java/RealWorldExample/.gitignore: -------------------------------------------------------------------------------- 1 | /patterns/ 2 | -------------------------------------------------------------------------------- /patterns/Creational/FactoryMethod/Java/RealWorldExample/.gitignore: -------------------------------------------------------------------------------- 1 | /patterns/ 2 | -------------------------------------------------------------------------------- /tests/PHP/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "phpunit/phpunit": "^11.4" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /docs/design-patterns.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/docs/design-patterns.jpeg -------------------------------------------------------------------------------- /docs/design-patterns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/docs/design-patterns.png -------------------------------------------------------------------------------- /docs/design-pattern-relationships.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/docs/design-pattern-relationships.png -------------------------------------------------------------------------------- /docs/UMLDiagrams/Creational/Singleton/singleton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/docs/UMLDiagrams/Creational/Singleton/singleton.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/UMLDiagrams/Behavioral/Strategy/strategy-structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/docs/UMLDiagrams/Behavioral/Strategy/strategy-structure.png -------------------------------------------------------------------------------- /patterns/Behavioral/Command/Go/RealWorldExample/commands.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/patterns/Behavioral/Command/Go/RealWorldExample/commands.sqlite -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/UMLDiagrams/Behavioral/Strategy/strategy-payment-methods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/docs/UMLDiagrams/Behavioral/Strategy/strategy-payment-methods.png -------------------------------------------------------------------------------- /patterns/Behavioral/Command/Java/RealWorldExample/commands.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/patterns/Behavioral/Command/Java/RealWorldExample/commands.sqlite -------------------------------------------------------------------------------- /patterns/Behavioral/Command/PHP/RealWorldExample/commands.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/patterns/Behavioral/Command/PHP/RealWorldExample/commands.sqlite -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /docs/UMLDiagrams/Creational/FactoryMethod/factory-notification-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/docs/UMLDiagrams/Creational/FactoryMethod/factory-notification-system.png -------------------------------------------------------------------------------- /patterns/Behavioral/Command/JavaScript/RealWorldExample/commands.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JawherKl/design-patterns-in-multiple-languages/HEAD/patterns/Behavioral/Command/JavaScript/RealWorldExample/commands.sqlite -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | ## Running the Tests: 2 | 1. PHP: Run vendor/bin/phpunit in the php/ directory. 3 | 2. Go: Run go test ./... in the go/ directory. 4 | 3. JavaScript: Run npx jest in the js/ directory. 5 | 4. Java: Run mvn test or gradle test depending on your build tool. -------------------------------------------------------------------------------- /tests/JavaScript/FactoryMethodTest.js: -------------------------------------------------------------------------------- 1 | const Factory = require('../patterns/creational/FactoryMethod/Factory'); 2 | 3 | test('Factory creates the correct product', () => { 4 | const factory = new Factory(); 5 | const product = factory.createProduct('ConcreteProduct'); 6 | expect(product.getName()).toBe('ConcreteProduct'); 7 | }); -------------------------------------------------------------------------------- /.idea/design-patterns-in-multiple-languages.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/material_theme_project_new.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /tests/Go/factory_method_test.go: -------------------------------------------------------------------------------- 1 | package factorymethod 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFactoryProducesCorrectObject(t *testing.T) { 8 | factory := Factory{} 9 | product := factory.CreateProduct("ConcreteProduct") 10 | if product.Name() != "ConcreteProduct" { 11 | t.Errorf("Expected ConcreteProduct, got %s", product.Name()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/PHP/FactoryMethodTest.php: -------------------------------------------------------------------------------- 1 | createProduct('ConcreteProduct'); 11 | $this->assertInstanceOf(ConcreteProduct::class, $product); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /patterns/Behavioral/TemplateMethod/README.md: -------------------------------------------------------------------------------- 1 | Template Method is a behavioral design pattern that allows you to define a skeleton of an algorithm in a base class and let subclasses override the steps without changing the overall algorithm’s structure. 2 | 3 | 4 | 5 | 6 | In this example, the Template Method pattern defines a skeleton of the algorithm of message posting to social networks. Each subclass represents a separate social network and implements all the steps differently, but reuses the base algorithm. -------------------------------------------------------------------------------- /patterns/Behavioral/Visitor/README.md: -------------------------------------------------------------------------------- 1 | Visitor is a behavioral design pattern that allows adding new behaviors to existing class hierarchy without altering any existing code. 2 | 3 | 4 | # RealWorldExample 5 | ## VistorInfra 6 | In this example, the Visitor pattern helps to introduce a reporting feature into an existing class hierarchy: Company > Department > Employee 7 | 8 | Once the Visitor infrastructure is added to the app, you can easily add other similar behaviors to the app, without changing the existing classes. 9 | 10 | -------------------------------------------------------------------------------- /patterns/Behavioral/Mediator/PHP/RealWorldExample/log.txt: -------------------------------------------------------------------------------- 1 | 2024-12-04 10:39:13: 'users:init' with data '"\/home\/jkallel\/Documents\/design-patterns-in-multiple-languages\/patterns\/Behavioral\/Mediator\/PHP\/RealWorldExampleusers.csv"' 2 | 2024-12-04 10:39:13: 'users:created' with data '{"attributes":{"name":"John Smith","email":"john99@example.com","id":"3104a6a328d3466d0c2ba2d39950b1d2"}}' 3 | 2024-12-04 10:39:13: 'users:deleted' with data '{"attributes":{"name":"John Smith","email":"john99@example.com","id":"3104a6a328d3466d0c2ba2d39950b1d2"}}' 4 | -------------------------------------------------------------------------------- /patterns/Behavioral/Observer/PHP/RealWorldExample/log.txt: -------------------------------------------------------------------------------- 1 | 2024-12-04 10:56:19: 'users:init' with data '"\/home\/jkallel\/Documents\/design-patterns-in-multiple-languages\/patterns\/Behavioral\/Observer\/PHP\/RealWorldExample\/users.csv"' 2 | 2024-12-04 10:56:19: 'users:created' with data '{"attributes":{"name":"John Doe","email":"johndoe@example.com","id":"58d8f7ed366e15e59661fe6a41e91369"}}' 3 | 2024-12-04 10:56:19: 'users:deleted' with data '{"attributes":{"name":"John Doe","email":"johndoe@example.com","id":"58d8f7ed366e15e59661fe6a41e91369"}}' 4 | -------------------------------------------------------------------------------- /patterns/Behavioral/Iterator/PHP/RealWorldExample/cats.csv: -------------------------------------------------------------------------------- 1 | name,age,owner,breed,image,color,texture,fur,size 2 | Siri,3,Alice,Siamese,siamese.jpg,cream,smooth,short,medium 3 | Bob,5,John,Maine Coon,mainecoon.jpg,gray,fluffy,long,large 4 | Mittens,2,Linda,Bengal,bengal.jpg,spotted,sleek,short,medium 5 | Whiskers,4,Mark,Persian,persian.jpg,white,silky,long,small 6 | Shadow,1,Emily,Russian Blue,russianblue.jpg,blue,soft,short,medium 7 | Leo,3,Anna,Sphinx,sphinx.jpg,pink,soft,none,medium 8 | Fluffy,7,James,Ragdoll,ragdoll.jpg,white,fluffy,long,large 9 | Luna,6,Emma,British Shorthair,britishshorthair.jpg,gray,velvety,short,medium -------------------------------------------------------------------------------- /patterns/Structural/Flyweight/PHP/RealWorldExample/cats.csv: -------------------------------------------------------------------------------- 1 | name,age,owner,breed,image,color,texture,fur,size 2 | Siri,3,Alice,Siamese,siamese.jpg,cream,smooth,short,medium 3 | Bob,5,John,Maine Coon,mainecoon.jpg,gray,fluffy,long,large 4 | Mittens,2,Linda,Bengal,bengal.jpg,spotted,sleek,short,medium 5 | Whiskers,4,Mark,Persian,persian.jpg,white,silky,long,small 6 | Shadow,1,Emily,Russian Blue,russianblue.jpg,blue,soft,short,medium 7 | Leo,3,Anna,Sphinx,sphinx.jpg,pink,soft,none,medium 8 | Fluffy,7,James,Ragdoll,ragdoll.jpg,white,fluffy,long,large 9 | Luna,6,Emma,British Shorthair,britishshorthair.jpg,gray,velvety,short,medium 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribuer au projet "Design Patterns in Multiple Languages" 2 | 3 | Merci de votre intérêt pour la contribution à ce projet ! Ce dépôt vise à fournir des exemples des modèles de conception (Design Patterns) implémentés en **PHP**, **Go**, **JavaScript** et **Java**. Nous sommes ravis de recevoir vos idées, corrections et améliorations. 4 | 5 | ## Comment contribuer 6 | 7 | ### 1. Forker le dépôt 8 | 9 | 1. Rendez-vous sur [le dépôt principal](https://github.com/JawherKl/design-patterns-in-multiple-languages). 10 | 2. Cliquez sur le bouton **Fork** en haut à droite. 11 | 3. Clonez votre fork sur votre machine locale : 12 | ```bash 13 | git clone https://github.com/votre-nom-utilisateur/design-patterns-in-multiple-languages.git 14 | -------------------------------------------------------------------------------- /.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 13 | 14 | 16 | 17 | 19 | 20 | 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 | } --------------------------------------------------------------------------------