├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── README.md ├── angular.json ├── browserslist ├── drawio ├── 01. Abstract Factory example.drawio ├── 01. Abstract Factory.drawio ├── 02. Singleton example.drawio ├── 02. Singleton.drawio ├── 03. Prototype example.drawio ├── 03. Prototype.drawio ├── 04. Builder example.drawio ├── 04. Builder.drawio ├── 05. Factory Method example.drawio ├── 05. Factory Method.drawio ├── 06. Adapter example.drawio ├── 06. Adapter.drawio ├── 07. Bridge example.drawio ├── 07. Bridge.drawio ├── 08. Composite example.drawio ├── 08. Composite.drawio ├── 09. Decorator example.drawio ├── 09. Decorator.drawio ├── 10. Facade example.drawio ├── 10. Facade.drawio ├── 11. Flyweight example.drawio ├── 11. Flyweight.drawio ├── 12. Proxy example.drawio ├── 12. Proxy.drawio ├── 13. Mediator example.drawio ├── 13. Mediator.drawio ├── 14. Iterator example.drawio ├── 14. Iterator.drawio ├── 15. Memento example.drawio ├── 15. Memento.drawio ├── 16. Strategy example.drawio ├── 16. Strategy.drawio ├── 17. Command example.drawio ├── 17. Command.drawio ├── 18. Observer example.drawio ├── 18. Observer.drawio ├── 19. Visitor example.drawio ├── 19. Visitor.drawio ├── 20. State example.drawio ├── 20. State.drawio ├── 21. Template Method example.drawio ├── 21. Template Method.drawio ├── 22. Chain Of Responsibility example.drawio ├── 22. Chain Of Responsibility.drawio └── 23. Interpreter.drawio ├── e2e ├── protractor.conf.js ├── src │ ├── app.e2e-spec.ts │ └── app.po.ts └── tsconfig.json ├── jest.config.js ├── package-lock.json ├── package.json ├── presentations ├── Behavioral_Patterns_GER.key ├── Behavioral_Patterns_GER.pdf ├── Behavioral_Patterns_GER.pptx ├── Creational_Patterns_GER.key ├── Creational_Patterns_GER.pdf ├── Creational_Patterns_GER.pptx ├── Structural_Patterns_GER.key ├── Structural_Patterns_GER.pdf └── Structural_Patterns_GER.pptx ├── readme └── images │ ├── 01. Abstract Factory example.jpg │ ├── 01. Abstract Factory.jpg │ ├── 02. Singleton example.jpg │ ├── 02. Singleton.jpg │ ├── 03. Prototype example.jpg │ ├── 03. Prototype.jpg │ ├── 04. Builder example.jpg │ ├── 04. Builder.jpg │ ├── 05. Factory Method example.jpg │ ├── 05. Factory Method.jpg │ ├── 06. Adapter example.jpg │ ├── 06. Adapter.jpg │ ├── 07. Bridge example.jpg │ ├── 07. Bridge.jpg │ ├── 08. Composite example.jpg │ ├── 08. Composite.jpg │ ├── 09. Decorator example.jpg │ ├── 09. Decorator.jpg │ ├── 10. Facade example.jpg │ ├── 10. Facade.jpg │ ├── 11. Flyweight example.jpg │ ├── 11. Flyweight.jpg │ ├── 12. Proxy example.jpg │ ├── 12. Proxy.jpg │ ├── 13. Mediator example.jpg │ ├── 13. Mediator.jpg │ ├── 14. Iterator example.jpg │ ├── 14. Iterator.jpg │ ├── 15. Memento example.jpg │ ├── 15. Memento.jpg │ ├── 16. Strategy example.jpg │ ├── 16. Strategy.jpg │ ├── 17. Command example.jpg │ ├── 17. Command.jpg │ ├── 18. Observer example.jpg │ ├── 18. Observer.jpg │ ├── 19. Visitor example.jpg │ ├── 19. Visitor.jpg │ ├── 20. State example.jpg │ ├── 20. State.jpg │ ├── 21. Template Method example.jpg │ ├── 21. Template Method.jpg │ ├── 22. Chain Of Responsibility example.jpg │ ├── 22. Chain Of Responsibility.jpg │ └── 23. Interpreter.jpg ├── setup-jest.ts ├── src ├── app │ ├── 01. Abstract Factory │ │ ├── abstract-factory.module.ts │ │ ├── abstract-factory.routes.ts │ │ ├── abstract-factory │ │ │ ├── abstract-factory.component.html │ │ │ ├── abstract-factory.component.scss │ │ │ ├── abstract-factory.component.spec.ts │ │ │ └── abstract-factory.component.ts │ │ └── models │ │ │ ├── factory.model.ts │ │ │ ├── font.model.ts │ │ │ ├── style.model.ts │ │ │ └── theme.model.ts │ ├── 02. Singleton │ │ ├── models │ │ │ ├── random.utils.ts │ │ │ └── tea.model.ts │ │ ├── singleton.module.ts │ │ ├── singleton.routes.ts │ │ └── singleton │ │ │ ├── singleton.component.html │ │ │ ├── singleton.component.scss │ │ │ ├── singleton.component.spec.ts │ │ │ └── singleton.component.ts │ ├── 03. Prototype │ │ ├── models │ │ │ ├── car.model.ts │ │ │ └── engine.model.ts │ │ ├── prototype.module.ts │ │ ├── prototype.routes.ts │ │ └── prototype │ │ │ ├── prototype.component.html │ │ │ ├── prototype.component.scss │ │ │ ├── prototype.component.spec.ts │ │ │ └── prototype.component.ts │ ├── 04. Builder │ │ ├── builder-routing.module.ts │ │ ├── builder.module.ts │ │ ├── builder │ │ │ ├── builder.component.html │ │ │ ├── builder.component.scss │ │ │ ├── builder.component.spec.ts │ │ │ └── builder.component.ts │ │ └── models │ │ │ ├── builder.model.ts │ │ │ ├── director.model.ts │ │ │ └── house.model.ts │ ├── 05. Factory Method │ │ ├── factory-method-routing.module.ts │ │ ├── factory-method.module.ts │ │ ├── factory-method │ │ │ ├── factory-method.component.html │ │ │ ├── factory-method.component.scss │ │ │ ├── factory-method.component.spec.ts │ │ │ └── factory-method.component.ts │ │ └── models │ │ │ ├── client.utils.ts │ │ │ ├── creator.model.ts │ │ │ ├── food-planning-history.model.ts │ │ │ └── food.model.ts │ ├── 06. Adapter │ │ ├── adapter-routing.module.ts │ │ ├── adapter.module.ts │ │ ├── adapter │ │ │ ├── adapter.component.html │ │ │ ├── adapter.component.scss │ │ │ └── adapter.component.ts │ │ └── models │ │ │ ├── cat.adapter.ts │ │ │ ├── cat.model.ts │ │ │ └── toy.model.ts │ ├── 07. Bridge │ │ ├── bridge-routing.module.ts │ │ ├── bridge.module.ts │ │ ├── bridge │ │ │ ├── bridge.component.html │ │ │ ├── bridge.component.scss │ │ │ └── bridge.component.ts │ │ └── models │ │ │ ├── device.model.ts │ │ │ └── remote.model.ts │ ├── 08. Composite │ │ ├── composite-routing.module.ts │ │ ├── composite.module.ts │ │ ├── composite │ │ │ ├── composite.component.html │ │ │ ├── composite.component.scss │ │ │ └── composite.component.ts │ │ └── models │ │ │ ├── soldier.composite.ts │ │ │ ├── soldier.leaf.ts │ │ │ └── soldier.model.ts │ ├── 09. Decorator │ │ ├── decorator-routing.module.ts │ │ ├── decorator.module.ts │ │ ├── decorator │ │ │ ├── decorator.component.html │ │ │ ├── decorator.component.scss │ │ │ └── decorator.component.ts │ │ └── models │ │ │ ├── extend-topping.decorator.ts │ │ │ ├── pizza.model.ts │ │ │ └── topping.decorator.ts │ ├── 10. Facade │ │ ├── facade-routing.module.ts │ │ ├── facade.module.ts │ │ ├── facade │ │ │ ├── facade.component.html │ │ │ ├── facade.component.scss │ │ │ └── facade.component.ts │ │ └── models │ │ │ ├── drink.model.ts │ │ │ ├── facade.model.ts │ │ │ ├── mill.model.ts │ │ │ └── trader.model.ts │ ├── 11. Flyweight │ │ ├── flyweight-routing.module.ts │ │ ├── flyweight.module.ts │ │ ├── flyweight │ │ │ ├── flyweight.component.html │ │ │ ├── flyweight.component.scss │ │ │ └── flyweight.component.ts │ │ └── models │ │ │ ├── brush-size.enum.ts │ │ │ ├── pen.factory.ts │ │ │ └── pen.model.ts │ ├── 12. Proxy │ │ ├── models │ │ │ └── internet.model.ts │ │ ├── proxy-routing.module.ts │ │ ├── proxy.module.ts │ │ └── proxy │ │ │ ├── proxy.component.html │ │ │ ├── proxy.component.scss │ │ │ └── proxy.component.ts │ ├── 13. Mediator │ │ ├── mediator-routing.module.ts │ │ ├── mediator.module.ts │ │ ├── mediator │ │ │ ├── mediator.component.html │ │ │ ├── mediator.component.scss │ │ │ └── mediator.component.ts │ │ └── models │ │ │ ├── chat-room.mediator.ts │ │ │ ├── chat-user.model.ts │ │ │ ├── mediator.interface.ts │ │ │ └── user.model.ts │ ├── 14. Iterator │ │ ├── iterator-routing.module.ts │ │ ├── iterator.module.ts │ │ ├── iterator │ │ │ ├── iterator.component.html │ │ │ ├── iterator.component.scss │ │ │ └── iterator.component.ts │ │ └── models │ │ │ ├── aggregator.interface.ts │ │ │ ├── iterator.interface.ts │ │ │ ├── iterator.model.ts │ │ │ └── words-collection.model.ts │ ├── 15. Memento │ │ ├── memento-routing.module.ts │ │ ├── memento.module.ts │ │ ├── memento │ │ │ ├── memento.component.html │ │ │ ├── memento.component.scss │ │ │ └── memento.component.ts │ │ └── models │ │ │ ├── card.model.ts │ │ │ ├── care-taker.model.ts │ │ │ ├── memento.model.ts │ │ │ └── orginator.model.ts │ ├── 16. Strategy │ │ ├── models │ │ │ ├── algorithm.model.ts │ │ │ └── strategy.model.ts │ │ ├── strategy-routing.module.ts │ │ ├── strategy.module.ts │ │ └── strategy │ │ │ ├── strategy.component.html │ │ │ ├── strategy.component.scss │ │ │ └── strategy.component.ts │ ├── 17. Command │ │ ├── command-routing.module.ts │ │ ├── command.module.ts │ │ ├── command │ │ │ ├── command.component.html │ │ │ ├── command.component.scss │ │ │ ├── command.component.spec.ts │ │ │ └── command.component.ts │ │ └── models │ │ │ ├── command.interface.ts │ │ │ ├── editor.command.ts │ │ │ ├── editor.invoker.ts │ │ │ └── editor.model.ts │ ├── 18. Observer │ │ ├── models │ │ │ ├── channel-clients.model.ts │ │ │ ├── channel-server.model.ts │ │ │ └── interfaces.ts │ │ ├── observer-routing.module.ts │ │ ├── observer.module.ts │ │ └── observer │ │ │ ├── observer.component.html │ │ │ ├── observer.component.scss │ │ │ └── observer.component.ts │ ├── 19. Visitor │ │ ├── models │ │ │ ├── fruit.factory.ts │ │ │ ├── fruit.interface.ts │ │ │ ├── fruit.model.ts │ │ │ ├── fruit.visitor.ts │ │ │ └── size.enum.ts │ │ ├── visitor-routing.module.ts │ │ ├── visitor.module.ts │ │ └── visitor │ │ │ ├── visitor.component.html │ │ │ ├── visitor.component.scss │ │ │ └── visitor.component.ts │ ├── 20. State │ │ ├── models │ │ │ ├── phone.context.ts │ │ │ ├── phone.options.ts │ │ │ └── screen.state.ts │ │ ├── state-routing.module.ts │ │ ├── state.module.ts │ │ └── state │ │ │ ├── state.component.html │ │ │ ├── state.component.scss │ │ │ └── state.component.ts │ ├── 21. Template Method │ │ ├── models │ │ │ ├── online.order.ts │ │ │ ├── order.template.ts │ │ │ └── store.order.ts │ │ ├── template-method-routing.module.ts │ │ ├── template-method.module.ts │ │ └── template-method │ │ │ ├── template-method.component.html │ │ │ ├── template-method.component.scss │ │ │ └── template-method.component.ts │ ├── 22. Chain of Responsibility │ │ ├── chain-of-responsibility-routing.module.ts │ │ ├── chain-of-responsibility.module.ts │ │ ├── chain-of-responsibility │ │ │ ├── chain-of-responsibility.component.html │ │ │ ├── chain-of-responsibility.component.scss │ │ │ └── chain-of-responsibility.component.ts │ │ └── models │ │ │ ├── handler.abstract.ts │ │ │ ├── handler.interface.ts │ │ │ └── handler.model.ts │ ├── 23. Interpreter │ │ ├── interpreter-routing.module.ts │ │ ├── interpreter.module.ts │ │ └── interpreter │ │ │ ├── interpreter.component.html │ │ │ ├── interpreter.component.scss │ │ │ └── interpreter.component.ts │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.ts │ ├── app.module.ts │ ├── modules │ │ └── angular-material.module.ts │ └── xx. components │ │ └── Home │ │ ├── home-routing.module.ts │ │ ├── home.module.ts │ │ └── home │ │ ├── home.component.html │ │ ├── home.component.scss │ │ └── home.component.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts └── styles.scss ├── test-config.helper.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | package.json 2 | package-lock.json 3 | dist 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | ecmaVersion: 2020, 6 | sourceType: 'module' 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/eslint-recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | 'plugin:prettier/recommended', 13 | 'prettier', 14 | 'prettier/@typescript-eslint' 15 | ], 16 | root: true, 17 | env: { 18 | node: true, 19 | jest: true 20 | }, 21 | rules: { 22 | '@typescript-eslint/interface-name-prefix': 'off', 23 | '@typescript-eslint/explicit-function-return-type': 'off', 24 | '@typescript-eslint/no-explicit-any': 'off', 25 | 'no-use-before-define': 'off', 26 | '@typescript-eslint/no-use-before-define': 'off', 27 | '@typescript-eslint/no-empty-function': 'off', 28 | '@typescript-eslint/ban-ts-ignore': 'off' 29 | }, 30 | ignorePatterns: ['*.json', '*.graphql'] 31 | }; 32 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", // Specifies the ESLint parser 3 | "extends": [ 4 | "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin 5 | "plugin:@typescript-eslint/eslint-recommended", 6 | "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier 7 | "plugin:prettier/recommended", // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 8 | "prettier", 9 | "prettier/@typescript-eslint" 10 | ], 11 | "parserOptions": { 12 | "ecmaVersion": 2020, // Allows for the parsing of modern ECMAScript features 13 | "sourceType": "module" // Allows for the use of imports 14 | }, 15 | "plugins": ["@typescript-eslint/eslint-plugin"], 16 | "rules": { 17 | "@typescript-eslint/interface-name-prefix": "off" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth":120, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "trailingComma": "none", 6 | "arrowParens": "avoid", 7 | "endOfLine": "auto" 8 | } 9 | -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /drawio/02. Singleton example.drawio: -------------------------------------------------------------------------------- 1 | 7Zhdb9owFIZ/DdJ2wUQSPi9J6LpORaoGUi8nNzGJi+PDHDOgv37HiU0IAY1NjbgoEhLx62PHPs9rx0nLC9LtvSSrZAoR5S23E21b3qTluk6/28M/rewKZdAxQixZZIJKYcbeqBE7Rl2ziGaVQAXAFVtVxRCEoKGqaERK2FTDFsCrd12RmNaEWUh4XX1mkUoKdegOSv0bZXFi7+z0R0VNSmywmUmWkAg2B5J31/ICCaCKq3QbUK6TZ/NStPt6pnY/MEmFuqTBzv35OhyPpmTuzr3p0+vz8vt92zHd/CZ8bWZsRqt2NgUS1iKiupdOy/M3CVN0tiKhrt0gdNQSlXIsOXhpuqNS0e3ZgTr76aNvKKRUyR2GbKvojWMcz5Q3Zf5dqyUHuXeHRiSGebzvukwLXpjM/EuWaknyOQmXc0pqyco2LOVEYMlfgFAzU6NTQziLBV6HmAcqUdBZYmi1salQoJMZJoxHj2QHaz2vTOGNbMlPQLI37JbYdGO1VGbVuP1KxEy3NNAkzTDmySJwjqQp2VYCH0mmjBAC52SVsZf9NFIiYyZ8UApSE/QO0L0j6L06dGd0CnrXbQh6rwa9naMmyEy3FXgp9CoYY+msHzAjKuckYUkD4IDgJwIKgzDOjyTrEU4X6qxDMlx9TMSPecykWyo/TF60BNh2wfMNJ2FRRIWmCzh6UqDU3FbAhMrz1vPxh+kNOl96rR4OPMCyU5bxp8OlCgDnLQnLqVL0yYZqr1xmgfOLq+4LYwQ09WU+6DdkA/ekDXQTzV2s0xdcyzfq70u9516Zev8kdbVbmfWO2cDM40VeiSPr/1rrB7mfbwSo5HuBFT+sPw4fgd2mzDIYXtks3t/PUJzlIAvg9iDp/BftFLlxWuKda/qTtlOzgFe3gHcCNycvlD9BxhQD3b8sYo9scK2dwOl0L6M7bAhutwa3ffC8//T5w67txog71978ByfWs3949oupejDHPzTA7QDYqB28a2/vwzN2QBfM8UBgHWCPBDf+78u/f+EDoDH+o/P8HyJL//Yi0Az90aXfAZqib79G1fCHAMvb2m/25d9p7u0fi+W317zu4Au2d/cH -------------------------------------------------------------------------------- /drawio/02. Singleton.drawio: -------------------------------------------------------------------------------- 1 | 7ZdRb9owEMc/TaTtoRNJSEofIXTdpiJVo1IfKzcxiYvjQ86xQD/9zolDCAGNTUV7qRQJ+++zY/9/dwYcP8o3d5qtshkkXDreINk4/tTxPDccBvRhlG2thEFYC6kWiQ1qhbl441YcWHUtEl50AhFAolh1xRiU4jF2NKY1lN2wBcjuW1cs5T1hHjPZV59EglmtjrzrVv/GRZo1b3bDm3okZ02wPUmRsQTKPcm/dfxIA2DdyjcRl8a8xpd63tcTo7uNaa7wnAlb7/l1NL6ZsUfv0Z89vD4tf9xduXaZX0yu7YntbnHbWKBhrRJuVhk4/qTMBPL5isVmtCTopGWYS+q51LTLcY18c3Kj7u74lDccco56SyGbLnqbMa5v+2Xrv9do2b73gRWZZZ7ulm5toYZ15m9c6pk0FyqVHEH13CpKkUumqDdZgMK5HTHeMClSRe2YjOCaBGOToFwb2wEE42acCZncsy2szcEKZPGy6U0y0OKNlmWN3zSs0ZaNF3Yi5mampaZ5QTEPDQP3QJqxTSfwnhVohRikZKtCvOyOkTOdCjUBRMht0DtQ9w+oB33q7s0x6q53IepBj/pVhZoRMzNXUVOZMhhT73RCkCVYgdKw5BFIIPJTBXWGCCkPpCZJJF/gyRQpqP7ohfdVzHTYKj+tMUYCmruQ1ZWTiSThyuAF2j6rWRpwKxAKK+OCCT3kbzT4EjgBbTyivtv26THhGiOgg2smKqycEqXkJlnOy4HT5dVPDJsJXnheIjRx754H/p+vSCkqdjXj5nvC/SfAOaGSvCX6aIBPr9wedb9P3T9CWLIXLh+gECjArK/r2APy/wtu4J0Hd3QhtsOjNb4r5k+fP8r5nYmHZ97rFyvn6yPlPNm/2FOO3+3dTvw/bveLpsPocrc7ddtf19XY3n8U//Y3 -------------------------------------------------------------------------------- /drawio/03. Prototype.drawio: -------------------------------------------------------------------------------- 1 | 7Vnbbts4EP0aA7sPCayrncdIbtoFUqyxabHJIy3RFhFK1FJ0bPfrdyiRutuW0zhugTRAYw7JkXjOmaORM7L8ePuZozT6ykJMR+Y43I6s2cg0Ddd24JeM7IqIa0+LwIqTUC2qAg/kB1bBsYquSYizxkLBGBUkbQYDliQ4EI0Y4pxtmsuWjDavmqIV7gQeAkS70X9JKKIiOjUnVfwLJqtIX9lwb4qZGOnF6iRZhEK2qYWsTyPL54yJ4lO89TGV4Glcin13e2bLG+M4EUM2THzf3vp/P2bUehbfw6fs8Wl7pbK8ILpWB1Y3K3YaAc7WSYhlkvHI8jYREfghRYGc3QDnEItETGFkwMfuTekrYC7wthZSN/kZsxgLvoMlata0FWBKMeZYjTcV/q6ORTXsS6SR4nxV5q5ggQ8KmRNQMntQcilc1ksbWLn/rSWbXoz4iiQj6xZmx+kW/s+hGRfxK8HSYs6uzQE64gpRslL7AkAQ8yonfFqp3/mVSS2AYkkD7Y7+kjmWkiwdbm5pZARoSPsqC96J6MCcM8HELsW1/Yv2aoil7VjEJWi60vX5jP1HfRXIFC9FDeVubrk2oCzBf/xZrOs7UO3mW2UhBU3AJ24LymY5qZ4icFZc3WOwaknzql8SqTlvyRKhXM4w1fgOxYRKtX/B9AXLrG9eVPa0VVRmt6iMaU9RueeqqZvjzoOT8FZaOIwWlAXPAEWIsij3IokLzN/lqObOBKM6sDX8ADa+e5TLrk09fKrPzbZlDjna6dGWiGLbxFHDp9pUtUsOdvUUc8wJwAT1WwT3MpixNQ/wAZgs9cwDUWNx3KJw2HicdfVQ51tzyzFFgrw0n3h9hKt0c0bgGJVhT5rasp2WZopDql31J1QrkW0dSVSg0EmU668840/YvHuSJkOCYpaE3yLpQnvFaNp7xGjUpTi+doaKsa7Ea8txDqsRBm8nxguKzBo3tWG1H/aDRdZKZNrGu4pMa/ydjW/qvM75zIs5n26xf2Xrs1u9qtN+XA5VpTs+kujc1jfpqNJnScCBybIt6uo025CYogTrvkbNGLVGSLWxltffLwURoeE92rG1ZDgTKHjWIy9inPyAtEjLGaa5bp7Aq+srHuROJTmOZXM515IzWqGvaNtYeI8yoQIBoxSlGVmUxyiaSY8JweJjih7ejTk3LTOzL92NmdPjrkRJznQmOHsuX4YlSLK19RllsuYTli9q9cFt8mMShjRPBm+SJFl9k2KYXRlV5D7fOLOqyD8KBhkCSSKBCpokJxQtMJ2zjAjCZH5erPVSWS85Vo43cmZ5hAtQNhwCkZw/DPRvcCZ6mT1cK8f51s8Ydxi903Ox29dsH3r/aTEv301L5ltMn05+UflNnu0uz3bz/SkCyeCkh/smxx7A6stuCtg2fRgb1fhyArDsYQLQQnlzBVjH7d3o0P5h76+zd2v6q9n7gBebD3dvVspvY+7dzu3D29+R/stbe7e4fUqwek8Y4OfjnzbqHp38rt5devChL0rtHn4d81z8dgucpZgjaYYf5X1qebuDBXHA3vv4P1t9290vjHK6+9iufffT7thWHIXSFTThI9Na5D8tIUB86cifjmpgxs3/vU2lTYwBlWb0IG2d3iXBsPpDa/GdSfXnauvT/w== -------------------------------------------------------------------------------- /drawio/06. Adapter.drawio: -------------------------------------------------------------------------------- 1 | 7Vpbc+MmFP41nmkf3NHdzmPs3LZNppl1pm32pYMlbLFBwkE4tvfXFyTQBUlrxbE2aes4k+gc4ADnO3xwsAb2NNpeU7AK70gA8cAygu3AvhhYlmkYZ/yf0Owyjeu5mWJJUSArFYoZ+gZVS6ldowAmlYqMEMzQqqr0SRxDn1V0gFKyqVZbEFztdQWWsKaY+QDXtX+igIWZdmyNCv0NRMtQ9Wx6csIRUJXlTJIQBGRTUtmXA3tKCWHZU7SdQiycp/yStbtqKc0HRmHMujQIgufhp+svL0NEbx7/gPTL1d+zoSVH+wLwWs5YjpbtlAsoWccBFFaMgT3ZhIjB2Qr4onTDQee6kEWYSyZ/rI9KDvQFUga3JZUc5TUkEWR0x6uoUoW9Chkpbgr/jwypC0u+tz2pBBLzZW66cAt/kJ55hZdGNSedB2DFIK35KtmgCIOYS5MFidlMlgjPAIyWMX/2uWd4S3siPIJ4pJ3LAkaEL/0Q4eAW7MhaTCthwH9S0iQkFH3jZoHyNi+mTC4ay6vUmImWEjMKE17nXoFiaqo7sK1UvAUJkwqfYAxWCZrn04gAXaJ4Qhgjkax0BMxtq4q5ZdRBN70G0Mfe2zFfTuju7ldKzZHzmS9mtP0NLYdmDfOh6CbFnSvOuXAuBT0I+JxZCg4lT3BKMOFoX8QkiwqEsaZSgYHhgrWGRcJXHIqXt2mdC6fQfJa+ECrC2y5wSjIhCgIYC0gJAwxk+AmwVgTFLHWWO+G/3KVT4xd34PKBT7lsFjL/FdUpm5KYzwWgFF3Ig2MDRYBMWkCuhkL7gqoHgwLf64a9dQTsG4c33k+KGKXYZRirncE8COCIQ4VhgeiDAPxiaNZQt+uo2w0IYzCH+J4kiCEi7NOsroZ8N3C7IdlppSs2tzou7J6wNe0GcPlsDQqf13zqP/38P1/Px4fc68jlva1ndaCoYO7hdFFUoPae1+I4Jje5jOWN1Zb/Td1jZPphCqEoc0plIkqGEntRJvf53CZ/Wsr/ac+opACRiAlclz4JGwtx2FLqapOKRe4bpPcyp7qGx1ncOGlxYBluJB5iBukpSx/+A3cBZKUuM3v7euUVV7oupGIc6sivOjLbXXYQWNkyzNGq29YWf7cZaBTRvMg1JigtZ0Eb6oyYOcC0pHwFIoTFyrmB+AUKq0c/YeunrbHdbYGO+jpgm/XTVs3FMA7ORULHpTkm4mw7CUASpomJ8Asvv0q9mtIil8qOLfmPu43u/hLVOC1K8bFcdrHNbQhpp6QtYqVmXHoslRSNhKDatGKVkDX14X6SZdlq209tMKjksXXom7ClEAOGXqqpbhO40ty92GuKMLLOqmHkmFp8ZLOUrcqpqWbIcfcYytxQM5TGWj7HN4Sfc9ofCo1S5OlN3nr+L2P1ZAV9tED+Z53d/0Nc7rp65uzWydxpIHOvtxO2+yoyDxCISBw8hALtVha3nBYWz4XHKqXvY/Eyh+eMfmwWV8RSpvHv3Ta8B4vbOosbh7L4WIvE8ejHsrhXizue6fgUMth2U3O6rjuMdPQN27Y7pni9XdGapzubzgl8vlA6Z/Bdb+R621KavqZo2eFPlzfHxd52umHf2+2NVU8OT7zeD6979kfjdUXjJ17fv7ZfgfcH4XWr7TL+xOu9Y//+vP66PPFYl37WB771U7vz/ms/Cd57JIyeUd0kXJ38uyaMI2+PoZ4TRqueMP6IABx94ADM37H60AGo3Vi44wMDcOzuMdR3ANZfLPpeAB73pmx02FWZ1dtd2Tt+k2FrlHboFxmWq9vpLaDMy83Xh23w9HX0u31GYPDszM8aXlqaYgRlXwe/01dNod6eZZhaljFqSDKsnpKMRrfVc4y29/te5bclBYHwvjqKDix7nn60IyrXL1zxqZ1neYmX/vSBgqPlek5HGJzXw8DF4kXXLNiL14Xty38A -------------------------------------------------------------------------------- /drawio/08. Composite.drawio: -------------------------------------------------------------------------------- 1 | 7Vpdc+MmFP01ntk+JCOEJFuPsZ1tp3Vm3M3ObPPUIRa26CLhIrK28+sLFrI+QI6SjezdqeOHiCuE4J5z4HLRAE6S7a8creM7FmE6cJ1oO4DTgesCAB35T1l2uSXwwtyw4iTSlUrDPXnG2qifWz2RCGe1ioIxKsi6blywNMULUbMhztmmXm3JaP2ta7TChuF+gahp/UIiEefWkTss7b9hsoqLN4NAjy9BRWU9kixGEdtUTPB2ACecMZFfJdsJpsp5hV/y5z623D10jONUdHkgiqO/wXb2590/7HcyEWH0HN9c6c5+Q/RJD1h3VuwKD3D2lEZYNeIM4HgTE4Hv12ih7m4k5tIWi4TKEpCXujnMBd629hMcRi9pg1mCBd/JKsUDvnZYwRhd3JTuDxxtiyuu9zxtRBry1aHp0ivyQjvG7qRP8I9/p7NROE9Y9mWOorn7QK6g4aQJS9YsVQNyg4ELgfLMYDhGj5ngSLJwODXcmG1IQlEqS+MlS8W9vqOchihZpfJ6IRvEXBqU/4jk4I2+IZhy8yImNJqhHXtSI84EWnwtSuOYcfIsm0UFEPI2F1pOnlOrca+e1HBynMk68wIc0DDdoW2t4gxlQhsWjFK0zsjjYRgJ4iuSjpkQLNGVWrC3MKSVDjCo02Fk0sG10QH4bk908F/WDCV7oCUb2NfDvKF8tCSUThhlEuVpyvaVCvQpXgoL9gmJIrpvTIqOpKvPigvTK1BaZvsHp7C0fNJuUCbOBBIoR0lBQtEjpnOWEUGYap/ndcdrRlKxd5U/HvjTvYWLCUsVpckePizR32DFAAuwR5XzMtoaXa8juqOesLXNh3KwDltjjpTHPvxigC2HJg5gN8B9Pd651uvQeia0ysTks0u6X1NiyRKcWuCuwzqWrpw4174C2J3IMijL58N81A1zNdX2AnoRaxiooyj6sDhM9fBGmg4z/4UH782DoXduHoAWHnCcSB9fqHAyKgCn4zrQHxfMoC/nwgqLiQrE5JAva8H7A18Aej7gPQP4GUbLHymel2P/eeN5txHPQ0vIB0YWxIO+tncguAT0XQV9UEdnRVsEbYW3r4geDC8h/elRh2YsZ0W9t2kcmrv0263AaZQZYEvjjcoUytIjZWoqHUuTnmtBkBc/EvX+vf8r6S7pNr77S9mvvdAvDA/Vu9Nixs1Lu2ppjjmRw1VrRG7cEpG35uvSQ+VO2ZIqFA21TskZe+IL3AFVubLIoKZDLISjWq7UBL+KdjFdc0ylyr7V06k2uHVzc8XuynIxamYDG8tAPkz9VDX92WjokB5sayh3g9GQpAbaVapp9bV2GDbSl27oHO+XHx6rLy/yHpRSODj8O9RhLnl9q2NUVYdzHYbhD6UQa3bc/QkE4g8b8ZT7VoE0AzPYj0D80SsFEhyt35NAbFFDuzIighKWRp9jkhqCKNXiei36AHVtAHf4kja0DEBVBNeuf1QHVkG9ffmApjiOiegc2gjcBnXeungEDc56HuxFG0NYfw8Ao6P9ataHfq1+T9rocGjYmzYCv6M0nPNL4xyUbx6XhQ2idmV8M+4CIOzE+DeQ7Nis0TxzlbtcbJDtjKkYeOaj1e86afcaGNtSMfazVc9t52XXbZsVdlvW9f+ZinkB2XbRtO/JT3e2au2dmVi9JGJ6x/yEZ6vW7tk+lrgcrZ6aBsEJj1at3bOl2C8nq2dgQnjCg1Vr99rS8Zdz1T5hB+CE56rW/o3MgJ4SrDcPVajf+WvSRnosDA0/AGDxg+/05AfLx0btO5tXfXvb3PusOIqUhwttDFz4uP81NCPtS1/9DIHJO8H+752waGb+XHMyAq4FjDd82SuL5afV+aa0/EAd3v4H -------------------------------------------------------------------------------- /drawio/12. Proxy.drawio: -------------------------------------------------------------------------------- 1 | 7Vptb+I4EP41SHcfqJI4Afqxge3u6tpT1Xa1u59OhhjirROzjinQX392YufFMSWl0GqlFqlkxvYknueZGduhB8bJ5jODy/iaRoj0PCfa9MCk53mu45yLL6nZFppgEBSKBcOR6lQp7vAT0iOVdoUjlDU6ckoJx8umckbTFM14QwcZo+tmtzklzbsu4QK1FHczSNra7zjicaEdecNK/wXhRazv7A7UhBOoO6uZZDGM6LqmAp96YMwo5cVVshkjIp2n/VKMu9zRWj4YQynvMmAzdzb/3l+MprfrYf87Gj39+PW17xdWHiFZqQmrh+Vb7QFGV2mEpBGnB8J1jDm6W8KZbF0LzIUu5gkRkisulTnEONrsfE63nL2gDaIJ4mwruqgB3kA5TDHGV+K6cr+v2RHXXA+GSgkV5IvSdOUVcaEcY3fSfwuSstll9A/3rh0HL26/XT70gcVJAyJuGy4brhr8XkkwwwSyBU574EK0OsuN+J97xin0fU6XRZtfaxP+4n1I8EKNmwlvIVbZFFcL9Z3fGdcUMJEokLb0VdqYS6y0ujmkYVG4Bpt3mbKWRivuVtNfMuCq0VOzr9AtTV3MpMt0mOvZubsnepCLCZrzmo/btmVfhn6vUMb/+tv+vEYYSE5jkRcuCowmOYqhQmxS3DCkotec5FE+x5Jk4ZymXGU111PyJUwwkez+gsgjklZtQdSKGEtc7Q6iUTOI3EE7ikpdPYpOFkQdMg1KowuZsoUUYZjQNLqPJcihaLjM3ZmnICEpj3p+03HCX2z7Q3Y7C7T4s9422ZQ2pLTV0gbz2jAh/ay1VIOkoMfsBCmjKzZD+9MJihqVpw2lDSqGCOT4sVmcbFgpczcUi8craQGM3ApGBtzFw6tR9WKyx5Ao9E1DXAQi4i1DOXXKOR7OpqDFpjFNZwyJ2qTzkkGubI0TAlOkY1K1uLUgVjkXhPZYn8WYRFdwS1cS8IzD2YOWwpgy/CTMQk1F0cx04HuDRo87OVKxiCGZC280i1xDdQ03jY5XMONKMaOEwGWGp+U0itwXUs5pso+kh2cSADpmksGpMslwfyYhOAc644w+lOs26SOZlceUUIHyJKV5JyOFm9gnOIpIbkwsenC6uJdcmPTdSnOVD5yASnOrvCBVjHLIYYGShITAKSI3NMMcU2mfFX3DpQyV3FVB2AsmuYZxwWoxCYhz+JBAf40ybgX22TDZj/ZWL766gTs6EbYjC7ZGrTaglgunEmoD2pejXUR6E1i/DazfrPWx4AhKLWA3QQ2FI8eyxgh4vbGQ3Up+N8SB3w1xzYyjQ+56LcxvGN1sPzL4kTJ44JlrwVEbcmCB3NXQHB/z9paqL8FWtTtfue8q5B8Bbw+fV+V4G/yni/gOe4GPCn4ovIHXDd5TlXCvnc8/aviJMbft7t82pNsbsrOzsw+gjw306L1zt15LdDzHmRIqV0phBLM4P0N2nznOyQ/I/rjjHMX84sDjmX7veezjNFeAATjw2Mcf7DF04mMfr71y+Jah5whIlyhtk6xBxzrjSuaAGnPcZ5lTstStc9Q584IONL1BDAunyD3LK2noduVh8H48NHci3jk4Eg87Hj8KVsBtrZtK+bsfODhv3Af4gUHrwuKhJLe+k9MbvNrZJsEobe+EXvRmrrlltpedl7ymM3OKbQniWSqTf4RjQavbbMvOUxUmnSbq5aUsNi9LE4Ph3nImJXuiMIL4wMwBXlLB3iRR+ObrK+/QgjU0Ms7pCpaVlLZXx7tJeeBbr7JoDYPOVeuI/Hk7WgCDFq1k0pUWrUJkGjpS/fAd+31OWj/aWzH7eeorygcIFwxGsijpHVvPA9P8Y+zkhH4eyE9r2ydaBvlfycZX1aNyKXr6eiTE6mc7BWrVj5/Ap/8B -------------------------------------------------------------------------------- /drawio/13. Mediator.drawio: -------------------------------------------------------------------------------- 1 | 5VlLc5swEP41HNtBCOH42NhJe2g6nbozSY4KUkBjjDxCjnF/fYURL4EDdvxIWvtgdrVapG/3Wy3YgpNF+lXgZXjHCY0sxyapBaeW44ARctRPptnkGg+CXBEIRrRRpZixP1Qrba1dMUKThqHkPJJs2VT6PI6pLxs6LARfN82eedS86xIHtKWY+Thqa+8ZkWGuvXJGlf4bZUFY3Bl443xkgQtjvZMkxISvayp4Y8GJ4FzmV4t0QqMMvAKXfN7tjtFyYYLGcsiEHw/fUYJsf26TyfLlF2L3c/wJaDcvOFrpHevVyk0BgeCrmNDMi23B63XIJJ0tsZ+NrlXQlS6Ui0hJQF1qd1RImu5cKCi3r/KG8gWVYqNMigmuRmxTpIKW11UAUGET1sAvkwbroAel7woXdaGh2QemFkp3lDAsuXgbWs88ljM9FxwDOs+AzmlDV+rq0LmnQs5pITfhUURxoMR3BR0cAl1X1p0MOthPTRqTL1mRU5JKxwWPye+QxQodNXDLstttoVSSrqyO20RRgSM2D6WZEh4z4TMqxGlaH5xuCill8qHwoa5rs5RUTcqEYk6+ekpaBdcIkdohXwmf9vNRYhFQ2Zd97ZDXQ1qEXdAIS/bSXFtXTLW7n5ypVVfMu2qmDxwZaZHvSc+ql2nDEXR7HOWbbjnapli5x8Ozzu0gbOwLKunHKHklHy9W8lALwZtUKgomr9H3KeL+vEFV4LV43EnciquP9bEe4lZkfaxz9dTE9d4dcV3HyB+ziRhMXKMCuPZ5ievtJG554oJWBr6rI7eTumc9ckcfDkNkpu/FMbzaq20p6h7BSbjFELzSvQDnnyiC7sAiuCPyJyiCDjSajvGhRXDc4+jERXC8V/K9sWcG1kE9s21dpGceevS6Fzt63UN7ZmQevWfumYuWYWDaxTymRkpdtiCNekOOOk4QdJws8MZHygIX9nRyO7JAhQVvambLzCDZvWA07r5PlVS5x+OmWPtFyimex+B1IDBhKoNUw6NcZ/7g0/ab2aryWNM/o+yr9IkUfE5rI972c5zXgch8MQM6OhzbO2OHA9rPyMegO/gv6A6Nog/NMA1uNUy6e+ehO7TtvdZl2O9bHpRY/UeQm1f/tMCbvw== -------------------------------------------------------------------------------- /drawio/14. Iterator.drawio: -------------------------------------------------------------------------------- 1 | 7Vptb6M4EP41ke4+tAIMSfOxJG23Uqtbbate776cHHDAWoNzxnnbX3822AEb8tK02Vx1l0gNM7YHe55nxoNpD4yy1R2Ds/SRxoj0PCde9cC453nu4CoQP1KzrjR9z60UCcOx6lQrnvAPpJSO0s5xjAqjI6eUcDwzlRHNcxRxQwcZo0uz25QS864zmKCW4imCpK39Hcc8rbRX3qDWf0E4SfWd3f6wasmg7qxWUqQwpsuGCtz0wIhRyqurbDVCRDpP+6Uad7uldTMxhnJ+yIC/nH547Yf09WaSUPQI+Ti6vfCuKjMLSOZqxWq2fK1dwOg8j5G04vRAuEwxR08zGMnWpQBd6FKeESG54rI9KzXRBWIcrRoqNcs7RDPE2Vp0Ua1AOUwxZqDEZe3+QPs0bbjeGyolVJAnG8u1V8SFcswbnOR2+KhPxG3DmeGp/t9zCWaYQZbgvAeuRaszW4m/pWOcSn/B6axq8xttwjf8AhKcqHGR8B9itU1xlajf8s64oYCZBIG0pXtpYyqh0mpziGFRuAbbd5mwlkYrrpOEoQRy1Bg/sXsL3czWpUw6TQe6Xp+7falHOZmgKW94uW1b9o0YEgu4F06CnLJffu2ethUOkshYJIjrCqxxCWeooBtX9w2p6DUlZbhPsWRbOKU5V+nN9ZR8CzNMJM2/ILJA0uqHB9PADCbXaUeTO+yIpsGpgsn7P5jawaQpaN7xeavtzxZoU8wKLuKr7Pe8a9Knm0MuSHHmKeBiTHOkJzERdQyC+XmmEs2ZzCr3Mn+P9rjlUydAoCtQlQGHHQnQ70iArjM4UQYErQw4ornYijhq7KmWz4slzgjMkfajanEbjldJDoTd+EQpJvEDXNO5XGDBYfRdS2FKGf4hzELtd9HMNFhe3+jxJEeqWpAhmV6+anhcS/UIV0bHB1hwpYgoIXBW4MlmGRV5Q8o5zVSnD0A/MMH33KCFvtdVTPZPtf0F++ttgkucC87o981Dh3SRDKQRJWKbAOOclp2sqLOhz3Ack9KYKNhxnjxLKowv3FrzUA4cg1rzTXlBqhjlkMMKJIkIgRNEvtICc0ylfVb1DWcU57x0VRD2gnGpYVzQWiwC4hI9JMBfooJ34rozTvaDrdHtHwbu1ameE7oeFLrrTAtyWbBsILcgfjvqVcCbAPttgH0zTaeCKyjvAN0ENxQOHTmXgYTZGwnZreWzIQ/8w5DXDPl46LvKWgtklMfX8kRCSDGGGc3j51Ru46FouC33yNLdQtKZ1zd3Q+E0tn5tCn/IMZdeoOXxamNESmstrTB/bVw3hwmxHiUFPWhr9i3onEVof4kv9pAE7YJZ2UOxcQTTBrm5VevEzBCBHC/MU5ouWJW5r5LEzarAfC4CdsKvFqlGNU9VLEOBv8dQ5YWWoZJlmzW+g3jtamIX8SaEyt07jGGRlkc67g7+lWVaF/9kuDcY6B5Kv8ugScATsQ/8+9nnWqQJro5kH3D2GDo1+w44Pnx/2lP0cY3stTt51VR9Y6o8nnd6928S7/bmCSxevv328vIaLO7485/+en1O4nkDsx4GzvBI4gXDSydwNh/PMnt1OXSH9af/U1mpd/n/ZE7cRbm9OdE7HzV9+1FtGBxHzYF15OmDn5sT9auhz1QKnrsSBGdMidbrpsB+jXRwShzuMbSFd4IIcN3oph63tpeuVvHg+v7ueVn99YJr2lczODYIdiWcRgzUR9xWLLzp9aJ5+NX9lNhB1e2ng0Mr6/gqeptMO9UBUafn2g+Sp/AcCBMGYyy8pI8Weh6YlF/ryEHop4H8ts4nREu//GxSxLugCOzSpOOgtgsJ/+1ICLF+715Rvv7vBXDzDw== -------------------------------------------------------------------------------- /drawio/16. Strategy.drawio: -------------------------------------------------------------------------------- 1 | 7Vptb+I4EP41SHcfWpFX2o8NtLsndaXqutJeP5rEJN514pwxBfrrb5zYeXGSAl04+oEiFWY8nsTPMzMeHEbONN184ShPvrEI05E9jjYjZzaybWty48Gb1GxLjW9bpSLmJFJGteKZvGGlHCvtikR42TIUjFFB8rYyZFmGQ9HSIc7Zum22YLR91RzFuKN4DhHtan+QSCSl9sae1PqvmMSJvrLl35YjKdLGaiXLBEVs3VA59yNnyhkT5ad0M8VUgqdxKec9DIxWN8ZxJvaZ8JNlXvaYpPz+zaLTIHeSH9mVpdbxiuhKrVjdrdhqCDhbZRGWXsYjJ1gnRODnHIVydA2kgy4RKQXJgo/KHeYCbwZv1KqWD3GDWYoF34KJmnCrAFMR4ylxXcPv+kqXNKB3tCFSlMeV5xoV+KCAOQSkHox8CpcN8hZS/r8rSWaQIh6TbOTcweg438D/Aphxqb8SLC/H3MYYwCWuECWxmhcCWJjXPuFTrN6LK5OGAqWSBNqV/pI+FpIqrW5PaXkEaIh5lTnvaLTiWXAkcLxtTJ+bxqDLTV3CJWY6z/XyrOGVfghjiheiAbLpG9GYcSKStELojz/7b9rIBRnYBKrDXcnUrOAyULzNyqsGDKwWtMj1BZGhFixYJlRts2wlP6CUUBnjXzF9xdLr0TPJdtqpBFB1cslye3JpcqpUcjqpNGVZyDGUFBVPVgfz5ZqkFGVY46hGrAbwKlucoJ+fMCE0ekRbtpLrWwoU/tJSkEAgvIFbpHGHYa7Jsv2WxbOcqeogxzKInzQXlqH6hjYtw0e0FEoRMkpRviTzahll0AZMCJYqoyOwb9lt9h27h/2+Suqfin1v92ZDSUH0UnD2q9pxJUYyk6aMMmB5lrHCyEg7k/uURBEtnMFuRbL4u4yF2ZVVax6LiTOn1vytUJAqzgQSqGRJUkLRHNMntiSCMOmfl7ZBzkgmCqi8YOTNCg0XENewCEQKrjCwv8ZLsS+xw7nTZVvntr8fuTcn4tbv4VYW5P5Sa7Aud7+KdYPlw4kvk77Nsdvl2G2X6gTCBWc9vLf5DQDT6fjak0zbU5CtWj4b+Y67H/k6SI7OfreNNOt6N9Uvdf1jdd35dHX95lLXfyO1J5+6rt9e6vr5yD97XdfHMO+lNs6iO3nSAtKcMllIgwgtk+LEQCYljD8UX4MK1EFqfhNqfOEBoPj2n8oMhBcpXE88Lc82zdHZVksbIop517anxJfGUD1LCnpSuQwcdY5/jDIMS2UrHuJdezN8hYdqj9/jeqCs95HLMUWCvLbvrY9d5e5JxnJji7CMMxTHKP3lmtSs5qGR4cid7HBULrrjCAICbRtmKtcGb7hauK56nmPEbumxjuQKwN8I7r6DnVMHt/Xh4J6cJbgnny64fc+ISfuDwX1jZonp6EjB7brnCG67E9ywexUb8qURP83x2mTP07WT9eGWu7ugXRrxHSlzUCfeR++pOnGr7/hMtuJhmdeXRvyE5Pd14n3kn64T7ztgG25WIoJSlkXfE/mQZLBLsd2hFvy66ktemmNDTYqUnjAnsFa5TRidy1kaF/20eGfj4v1vnYvZTXd2gn07F998sGM6GuhcjtZcdE986ueBRlAe9PjY7D9ijiIC1Ov6NLKdefEy6hboF558dYocjPjF33H2fFfvse/s+XZPXXAP3/NBrH8dUDJX/8bCuf8P -------------------------------------------------------------------------------- /drawio/20. State.drawio: -------------------------------------------------------------------------------- 1 | 7Vptb+I4EP41SHcfqEicBPjYwLbbu66uOlba2/tSGWKItU6cOqZAf/3ZiZ0Xx7xsF64rbUEq8die2PPMjJ9M2gOTZHvLYBZ/ohEiPXcQbXtg2nNdZzh2xY+U7EpJ4I5KwYrhSA2qBTP8gpRwoKRrHKG8NZBTSjjO2sIFTVO04C0ZZIxu2sOWlLTvmsEV6ghmC0i60i844nEpHbnDWv4R4VWs7+wE47IngXqw2kkew4huGiLwoQcmjFJeXiXbCSLSeNou5bybPb3VwhhK+SkTkhfwyJ/gLPsynfz1POs/zR5v+n6p5RmStdqwWizfaQswuk4jJJUMeiDcxJijWQYXsncjMBeymCdEtBxxqdQhxtF27zqdavfCbRBNEGc7MURP0NArj3GBam9q+/sDJYsbtq8sDRXmq0p3bRZxoSxjt9K/29sA4fzuz/iPaDzFy8e72W3fsVgpIOK2YdayVfC0lmiGCWQrnPbAtegdZFvxtzDNoJT3Oc3KPq/RJwzG+5DglZq3EOZCrNYprlbqt7gzbghgImEg3dad1LGUYGlxe0pLozANNu8yZx2JFsw45Kgxd26OFLLMlMVMGkxHud6bs3+brzIwQUvesLBFd7n9dJ5n5cQYphFBv/1uX7sREdK9sUgR1yVa0wLPUGE3LW8eUjFqSYqAX2LpbuGSplwlOMdV7RuYYCId/SMiz0hqtcVTJ3gsIbY3nsDAiCevG0+Oa4mn0aXCye2E04SmC4ZEYpE+5XQMnm9wQmCKtBFVj9OwugoXENrBWcSYRPdwR9dyczmHi2+6FcaU4RehFmqji26mkXKD1oiZnKlSIUPSkR80No4h+gS3rYH3MOdKsKCEwCzH82obpeOGlHOaqEFngL7KiAp6MLRADyzQB5eC3jt+3hBcAJ1zRr9VZ660kQyjCSVUoDxNaTHIiDkT+wRHESmUiQMLp6vP0hemfaeW3BcTp6CW/K2sIEWMCn+EJUoSEgLniDzQHHNMpX5Wjg0zilNemMoPe/60kDAunFpsAuICPiTQ36CcW4E9GCXH0daBHZwG7uhC2Nq4RDu3GkjLI69C2kD2+8EuA72Nq9fF1Wvn5li4CEotWLcxDYUdJ4MrX6LrTkTbqdtvBjjwTgNcO8b5E/nweDijNLqWPFy05oTK5BlGMI8LQikDUfTfFOdjYXXRah6RjZNQ2I7t/pHDhNVV82uzb7qtdMjWTre2mDemidbXRk89STb0nL2pN6drtkDHMRQHyAodwlrpQ1Hr6aOLdBNanZQZIpDj5/YDig1bpe5BenJ9KPSr7L4zyLTWUe5STWs+UZianMERTaUdOpqEQ8BdY5iKtb1Ldkd++xzzBwcXBowdGuPFRbmC2vMrk78+GEBgozVFjnvnM+fhM1V2q6is382AtkfDi/EZcEIGfCc0RoD8EKOxwXspRgO6lIahp7XY9TubOT/aNjpjrfNcis543Qx+iM5EGCY0jT7HshKxl8e43h4eUzUKPnLlVqzmGJFp0hg17QJMRhdbjzEZjfPbUBnPICD+K6mME4CrwXBcf0D7oBkGV+OxU3cbLriH57yCWlirtN36Y6tg0vXSX5hg/FDtuSqQvEXBxAp9t1b2q/KLI8DuD5yfoWBiXR2wYPteMLkg4P9nwcS6vBPKn2erl7y67mGc5Efpw/cAcQESAIz3hb753uJUDtCpGpjvE89UzfDAz1XNsOLXpcLqfZ/hrg2PM5nGisEIC8fRWanngnnxNbKVkC99+e2kNtETFJ/znO7e6ITygWPJB94Bp9yTD0SzfrVfglL/gwT48B8= -------------------------------------------------------------------------------- /drawio/21. Template Method example.drawio: -------------------------------------------------------------------------------- 1 | 7VpRj6M2EP41ka4PewJDgH3cJHfXqnvdtDn17p4qB7zBWoORcZrkfn3HYEIIkGO34diqSJHCjIfBnu8be2x5Ys2j/QeBk/AjDwibICPYT6zFBCHTvUXwpzSHXOMgL1dsBA20UalY0W9EKw2t3dKApBVDyTmTNKkqfR7HxJcVHRaC76pmj5xVv5rgDakpVj5mde1nGsgw13rILfU/E7oJiy+bzm3eEuHCWI8kDXHAdycq693EmgvOZf4U7eeEqeAVccnfe9/SeuyYILHs8sKDO0usL8kv6Nc/PfL75/j+N+PpBlm5m78x2+oR697KQxECwbdxQJQXY2LNdiGVZJVgX7XuAHTQhTJiIJnwqN0RIcm+taPmcfjAG8IjIsUBTIoXPB0xTZkigLsy/rahdeFJ7G1LK7HGfHN0XYYFHnRknhElsxakBxEQ8YlECcOSTJAzQZapojNx1Q+vUykwsNFdqN95QNMdjRiOQZo98liudIsKH2Z0E8OzD7EiAhQqkhToeKcbJFcB90PKgnt84Fs19lRi/6mQZiEX9Bu4xQUk0CykzizbqFis1JsaWEFSsFkWMJlnqo94XzG8x6nUCp8zhpOUro/DiLDY0HjGpeSRNroCMZBbJYZdJwZSUJwTAxl2T8RANWLcgPgXTT/QR/j4HQhrmK0IjmskgDDIDBzBn8icMw5oL2Kes4IydqYqiMGIctxCixTSksab+8xmYZeaP3QwlIrDu48sm4lCGgQkVpByiSXO8VNgJZzGMgvWdAY/iPPceDudTKHjc5DNUoafMhdyzmNFeppBSYAcO6II0g339qyrk+G54Ds9Yd9h5mQ0wy7HuFg+zBcBHAFUjJSIflKAL27MGupWHXWrAWGG14QteUol5cq/yG3PkB8KXMfpBq7XE7Z2A7YzhS1hUGQsBQ+2vkzf/JSnOIQGov2/zfDTNQz1xQjXHjjdpy2USPBh5MOP54NpDD3/Oy2EgB0QhfGOpBiAFKjjutEbKdwWUqiNkmbEXVYcjrTotYAwp2hgJnht64XgPknTbAP5pmGjUOVFXoSN7LgyO1xvYHbc1tixklyQjBU1uAc8L4AA/IfPC4zqeYHVcJJkOg0nSaaJesLdrB8ljbvG7ml9ezGtG1b/Rnj72jWaTUcC47axQ0Vo9EUJq75tbKREbxO92XaUMO4bByGE03EJ6I8QbQcJ475xMFJ4HReO/khRP0x4iFUdMBaE1ywI7VdYEDadGIwFYed9nvO6K8K2U4CxIuxvrv8OJ4YvCeub/7EkHJIRg9eExTI01oSviBWDF4Wow1kRiYM7dcsNpDXjqhSbBTgNs9taalGH9vdUfTbDACRdxkE9U7m2BZEShy/KDDDQ4tfTtsX+6ENJh1NpSQSFIatyM1fuqTzxBdLXk5bSkxIKR/nISFC7jXdW28Ho+Vb45ELc9PQKReuGXMLfa4a/CW9BGJaQiZWONAGu3S0V2cu607SrdadT1KGFi3xM+q2SNjVHlvEdR/mga46AI/hwYqaTsbXD6PwKnmdc7pdnXbKHh7wHZTIcA/4v8gP9wPx4AaVPc8qwKln11jDQSzLrillSbDlfUZocL3BqFk3dF6aJ7ZzR1+knTexnp4l9zTQBsbw+nJuXl7Ctd/8A -------------------------------------------------------------------------------- /drawio/21. Template Method.drawio: -------------------------------------------------------------------------------- 1 | 7Vhrb5swFP01SNuHTrySsI+FdA+t0apl3aPfXLgBawYz4zSkv37XYEIIpEmlZZ22SpHCPb527HOOuY4NJ0jLt4LkyYxHwAzbjErDmRq2bU1GNn4pZF0jY8+rgVjQSCe1wJzegwZNjS5pBEUnUXLOJM27YMizDELZwYgQfNVNW3DW/dWcxNAD5iFhffQrjWRSo549afF3QOOk+WVr/LpuSUmTrFdSJCTiqy3IuTCcQHAu66e0DIAp8hpe6n5v9rRuJiYgk8d0uPl07b5zR+/tL+cxGYd8xb6tzyy3HuaOsKVesZ6tXDcUCL7MIlCjmIbjrxIqYZ6TULWuUHTEEpkyjCx87M9KT/QOhIRyC9KzfAs8BSnWmKJb3YYxbRlPh6uWf9vUWLLFvdP0I1rzeDN0Sws+aGYew1KPpPPbQgoSyoCRojDssWE7lmLHmKgP0a3GZKo+u4QWK5oykmHkL3gm57pF0UcYjTN8DpE+EAgo2ija8Vw3SK4IDxPKokuy5ku19kKS8EcT+QkX9B6HJY0k2Cyk3lmu2cmYq55aWAEF5lw1ylk70IyUncRLUkgNhJwxkhf0drOMlIiYZj6Xkqc66XcYw+0awzL7zrDGA86wlEAncYZzePswWimNjuA/Nu8QRdKCMhZwxlHmacarpEZ+Bgs5IH5Ko4hVg+H+o1n8WZlhema1yGXVceq0yCdNg4IEl0SSWialCSO3wK54QSXlanxR5/o5p5msqBr5xmhaIUIGPFO2ppV+gPKvQFlgQNkHN9FhubW87pHqeifSdujV6Kv6A2nOiIQZyIRHL172FMf1yY3iOwo/XvR6x3f1dfv6Kohj3wWrikyCVoFsQPOutj7yGZivRkplO8DYauOnE947Tvjfsauv729Km07BPJtdJB9+xutg5p7Ze5TPBU1xr9zBxxwEUZvG+o/l365d9h6Nj7XHXi9M3Cf2Qr/27/OC/eyF03rh6Hp/snLv9cyAhIQCJOiD4N9z0kMO/p2TnnOs8t6plG/+jz6f9A7vYu9oudfd/fpUJ73Rc71/5DvePJUVnD9Y7wdnPHmu93+LF8ZPXe6t/t/7i1JCFvUrPYLn6roRo1vGVan1EdK12BrX4Ruqfr/SYuvKDEoqvykYua+j7zpJPU/L7WDdBBmub6uTCr8346mg7VZFnX5XgF6G6tTxcMEu+FKEcFhSPHbEIA8foiHqXLb2hR9SWgD+2cZ915nZkNR6uCvl8vYo4Xjdo4S7e0tYL1L32r4/3RlotHMtiYeS7kA1C72BKudt1jhkRgzba+A6vb1Mdy5+AQ== -------------------------------------------------------------------------------- /drawio/22. Chain Of Responsibility.drawio: -------------------------------------------------------------------------------- 1 | 7VlbT+M4FP41lXYfGOXe9pG0MKzErFgYaWeeVm7iNh6cOOO4tOXX73Hs3NMbtCoPgAQ9x/aJ/X3nO47dgT2J1185SqNvLMR0YBnhemBPB5ZlOmMb/knPRnlcSzsWnIS6U+V4Iq9YOw3tXZIQZ42OgjEqSNp0BixJcCAaPsQ5WzW7zRltPjVFC9xxPAWIdr3/klBEyjuyhpX/DpNFVDzZ9MaqJUZFZ72SLEIhW9Vc9s3AnnDGhPoUryeYSvAKXNS42y2t5cQ4TsQhA375D6/P6erp7/t/Xl3qDzdB8t+V6agwL4gu9Yr1bMWmgICzZRJiGcUY2P4qIgI/pSiQrSsgHXyRiClYJnzU4TAXeL11oma5fMgbzGIs+Aa66AFjDZjOGNPW9qrC3zW0L6phbw21E2nOF2XoChb4oJE5BqUekDwKj/XTBlTe76Vk048RX5BkYF9Dq5Gu4W+OjKH8V4Klqs2ptQFe4gpRstDjAkAL8yomfFro//mTSc2BYskC7Vp/yRhzyVXhbg5pRARoSPspM97xFI47lIQ0n2ExetbuC7607Yu4hKzQebE6c/tC3wQxxXNRw7gntgIgmWWpGqiW84h/L3Em/vizfwktZcg0J1ArrhVt05xYX5M4VXPwGfSa01z5cyLzzp+zROhKZ1ravkUxoTLj7zB9wTLqyXVl2y1hjbrCMt0eYZ1NV1ZHVxOWBBwLrJPrugN5tiIxRQkuYNQtZg13rRzb76cniAgN79GGLeXyMoGC58LyI8bJK4RFBezQzAuuLK/R40mO1EWRY5nRDwUVZsv1Da0bHe9RJrQjYJSiNCOzchkqg30mBIt1pxOQbzlN8m2rh3yvh3zvXOQfsPNQkhOdCc6ey+1XYiSFNGGUAcvThOWdWqprcx+TMKR5MNi6SLL4LnNhemVWnvt84NSuPI8aBeniTCCBFEuSEopmmD6wjAjCZHyu+vopI4nIoXL9gTvNPVxAWsMiEMm5wsD+CmfiUGK3S6fLtmYXUvUgckdn4tbtcjuxBtdGX51tcS73wZLzFsfH064k32TY6TLsNOt0BMmCkx7Wm+z6sJ6J8cWVPFsTsM3Kvhj1tnMY9UWKnJx7b19R7+6jn0X9bUXdMd0PVtSHn0X9Hcr2PnRRH30W9UtRf/GiPt6va5yE1/LCBayQoJgl4fdIntB8aLjNDz452mAVpddpHnEAIL75UTd+yjFfLLewp+syiLQ2hbUm4kfedWi72lZDDdPRdjVUGvWRD5gTAEluLrW6jMPOvVCrKsPi2ZIHeAdqxYUVFH+8i/wtVb6PbY4pEuSlObc+unW4B5nctR2jdQww22c7tSY9qn6b1A40bAUyW4HUojuBIEXQptZNi+/wCbvGznm51jv7j0ctsagZV9IpCXrHfZLRkdPNWoAysl2qmlEm301qCjK9jrz69FSX0M964149jWpqupJyGl5STtaHk5Pduqss7yWPlZPr7gm0RU4ny8juFed5M3L4xow0h40Kf8l09D5cOjpeM4uc8RvT0bP2BDp3OvbcDFKC9cPq2XjaK9JyFyu3R32gqZNl9rx4Oec6UJl2B4ldijztm9fBL16Nly7L3anKEyrw4PerLVcmZ5BgS4HlnfuxCrSsPYHOrcDuFd4kggMPuNi8++3QI85SOBORGaFEbHaptH3Bs+AolMoujoADy57lv62jIfjnrvztnCOhxct/zlMDSkr31QD3+BoAZvUFsKKu+hrdvvkf -------------------------------------------------------------------------------- /drawio/23. Interpreter.drawio: -------------------------------------------------------------------------------- 1 | 7Vpbb+I4FP41kXYfWmHnRh8LdGZ2t7Oqlmpm59EQQ6xxYuSYAebX73FikyuFaRvalShIzTk+Nvb5Pn++gOOOk+1HSVbxZxFR7uBBtHXciYMxCm8w/NOeXeEJUVA4lpJFJqh0TNlPapwD412ziGa1QCUEV2xVd85FmtK5qvmIlGJTD1sIXv/UFVnSlmM6J7zt/coiFRfeIQ5L/yfKlrH9ZBTcFCUJscFmJFlMIrGpuNw7xx1LIVTxlGzHlOvk2bwU9T4cKN13TNJUnVIhw3/5XzLvT7Vdxl+usM+S6bcrZHr7g/C1GbHprdrZFEixTiOqWxk47mgTM0WnKzLXpRsAHXyxSjhYCB5Nc1Qquj3YUbQfPvCGioQquYMQU8E3CTOMQdbelPn3bVLjSu5dG0gM5st902Va4MFk5heyhFtJup1lSpK5utuuJM0yJlIHA7FdpFPkhPpNTIgTTvS7mdVswxJOUrBGC5GqqSnROSScLVN4nkPCqASHTicDTt6aAiV01ucx49E92Ym1TkCmyPy7tUaxkOwnNEssLlAslZle3qAWMdU1DbowGIh5sFihhusz2dYC70mmjGMuOCerjM32w0iIXLJ0JJQSiQl6BXbgsE4PPGzTA4VBmx6h1xM7vONTiLMcaCCE+L7XEZ2jBeN8LLgAlCepyIMs+pwuVAf2CYsinjcGc5Cly0fNhckVKj33ecWJW3r+MVnQLikUUaRASUPCyYzyB5ExpUnsTmQRO1oJlqo8Vf7I8Se5R6qxSDWrWY4VBfQ3VDPgNGAPz6022gZd70Rwhz1h63dgO9KV9MyEqa9+g4UHxgzduAX3uDB+bxGgCDEEaAD+6xwo5n8dbq8Nt3YJqLvg+boTA3No2kGBOtQjSPl4cO1r0PEYbFTaR3lQlTLcGymGp5ECBz2xImix4pHKhKWEV9eD9yP4kIj/r+CjhuB7uEsTOvYDQV/bgeFF8F8g+MGTc9vO2WPg9iX4Xfvhi+CfnweudxoPetN4ewCtMOFvDfZF53vSeXf43nQeoYvQv2CCo0E33u9E6VH7VH+R+jdhwttrvduiwt1W0TTKWmCD81ZfK4I140LL6whcRn9RUJgfmP78PP+VqzG6Zepf7b4OfWN+M1H6ebKtGjtrpDDAohbyPevI613f3ITWUVbOrVrtByoZ5EkvOBWtplHr4rOh1DBusZZz+kTiDCCwBC3pUwTwu/GvAm5VXFJOFPtR71sX4qa5B03wymkhqK8iAWqsDsWYTK3qdWmjIdetN+SGjYaKQbcaygm4H+MLONm+VuqVk/hZnBwGfpOT/htz0gL+jkjpeg1S4meS0h8caahvUrbvw8acUfNhVU5WOFbfBb98o9i8AA469omoY/no7esB1L4PMpuFc6al9b1J+OZ5CTt2WIe1K2IkEWn0GLO0JVmlnmGvoWBWjFBdiMKjOmSlr6p7pQx2S98r6hQ+UabQGRfPY/Jyqk7h5ip8bp064YquN+bh5zHvbMRDp+7azsg8/Eq7NjQ80tAB4gETyK4SZo5Nh/vb2B2iG//pCdGIt4tYyfuiB686C2xSK7PgD3u2hZ3XyWuTO1pKEull3h5lHezO8lfjiAv+ha9frfMwlAT53+tcFnne+RY7MMtfaRTYlL91ce/+Aw== -------------------------------------------------------------------------------- /e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | browserName: 'chrome' 17 | }, 18 | directConnect: true, 19 | baseUrl: 'http://localhost:4201/', 20 | framework: 'jasmine', 21 | jasmineNodeOpts: { 22 | showColors: true, 23 | defaultTimeoutInterval: 30000, 24 | print: function() {} 25 | }, 26 | onPrepare() { 27 | require('ts-node').register({ 28 | project: require('path').join(__dirname, './tsconfig.json') 29 | }); 30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | import { browser, logging } from 'protractor'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', () => { 12 | page.navigateTo(); 13 | expect(page.getTitleText()).toEqual('design-patterns-in-angular app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo(): Promise { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText(): Promise { 9 | return element(by.css('app-root .content span')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | '@core/(.*)': '/src/app/core/$1', 4 | }, 5 | preset: 'jest-preset-angular', 6 | setupFilesAfterEnv: ['/setup-jest.ts'], 7 | }; 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "design-patterns-in-angular", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "test": "ng test", 9 | "lint": "ng lint", 10 | "e2e": "ng e2e" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "~11.0.0-next.5", 15 | "@angular/cdk": "^10.2.4", 16 | "@angular/common": "~11.0.0-next.5", 17 | "@angular/compiler": "~11.0.0-next.5", 18 | "@angular/core": "~11.0.0-next.5", 19 | "@angular/forms": "~11.0.0-next.5", 20 | "@angular/material": "^10.2.4", 21 | "@angular/platform-browser": "~11.0.0-next.5", 22 | "@angular/platform-browser-dynamic": "~11.0.0-next.5", 23 | "@angular/router": "~11.0.0-next.5", 24 | "@briebug/jest-schematic": "^3.1.0", 25 | "@typescript-eslint/parser": "^4.8.1", 26 | "rxjs": "~6.6.3", 27 | "ts-md5": "^1.2.7", 28 | "tslib": "^1.10.0", 29 | "zone.js": "~0.10.2" 30 | }, 31 | "devDependencies": { 32 | "@angular-builders/jest": "11.0.0", 33 | "@angular-devkit/build-angular": "~0.901.7", 34 | "@angular/cli": "^10.1.6", 35 | "@angular/compiler-cli": "~11.0.0-next.5", 36 | "@types/jasmine": "~3.5.0", 37 | "@types/jasminewd2": "~2.0.3", 38 | "@types/jest": "26.0.19", 39 | "@types/node": "^12.11.1", 40 | "@typescript-eslint/eslint-plugin": "^4.4.0", 41 | "codelyzer": "^5.1.2", 42 | "eslint": "^7.10.0", 43 | "eslint-config-prettier": "^6.11.0", 44 | "eslint-plugin-import": "^2.20.2", 45 | "eslint-plugin-prettier": "^3.1.4", 46 | "jest": "26.6.3", 47 | "prettier": "^2.0.4", 48 | "prettier-eslint": "^11.0.0", 49 | "protractor": "~7.0.0", 50 | "ts-node": "~8.3.0", 51 | "tslint": "~6.1.0", 52 | "typescript": "~4.0.3" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /presentations/Behavioral_Patterns_GER.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Behavioral_Patterns_GER.key -------------------------------------------------------------------------------- /presentations/Behavioral_Patterns_GER.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Behavioral_Patterns_GER.pdf -------------------------------------------------------------------------------- /presentations/Behavioral_Patterns_GER.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Behavioral_Patterns_GER.pptx -------------------------------------------------------------------------------- /presentations/Creational_Patterns_GER.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Creational_Patterns_GER.key -------------------------------------------------------------------------------- /presentations/Creational_Patterns_GER.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Creational_Patterns_GER.pdf -------------------------------------------------------------------------------- /presentations/Creational_Patterns_GER.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Creational_Patterns_GER.pptx -------------------------------------------------------------------------------- /presentations/Structural_Patterns_GER.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Structural_Patterns_GER.key -------------------------------------------------------------------------------- /presentations/Structural_Patterns_GER.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Structural_Patterns_GER.pdf -------------------------------------------------------------------------------- /presentations/Structural_Patterns_GER.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/presentations/Structural_Patterns_GER.pptx -------------------------------------------------------------------------------- /readme/images/01. Abstract Factory example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/01. Abstract Factory example.jpg -------------------------------------------------------------------------------- /readme/images/01. Abstract Factory.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/01. Abstract Factory.jpg -------------------------------------------------------------------------------- /readme/images/02. Singleton example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/02. Singleton example.jpg -------------------------------------------------------------------------------- /readme/images/02. Singleton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/02. Singleton.jpg -------------------------------------------------------------------------------- /readme/images/03. Prototype example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/03. Prototype example.jpg -------------------------------------------------------------------------------- /readme/images/03. Prototype.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/03. Prototype.jpg -------------------------------------------------------------------------------- /readme/images/04. Builder example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/04. Builder example.jpg -------------------------------------------------------------------------------- /readme/images/04. Builder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/04. Builder.jpg -------------------------------------------------------------------------------- /readme/images/05. Factory Method example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/05. Factory Method example.jpg -------------------------------------------------------------------------------- /readme/images/05. Factory Method.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/05. Factory Method.jpg -------------------------------------------------------------------------------- /readme/images/06. Adapter example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/06. Adapter example.jpg -------------------------------------------------------------------------------- /readme/images/06. Adapter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/06. Adapter.jpg -------------------------------------------------------------------------------- /readme/images/07. Bridge example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/07. Bridge example.jpg -------------------------------------------------------------------------------- /readme/images/07. Bridge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/07. Bridge.jpg -------------------------------------------------------------------------------- /readme/images/08. Composite example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/08. Composite example.jpg -------------------------------------------------------------------------------- /readme/images/08. Composite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/08. Composite.jpg -------------------------------------------------------------------------------- /readme/images/09. Decorator example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/09. Decorator example.jpg -------------------------------------------------------------------------------- /readme/images/09. Decorator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/09. Decorator.jpg -------------------------------------------------------------------------------- /readme/images/10. Facade example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/10. Facade example.jpg -------------------------------------------------------------------------------- /readme/images/10. Facade.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/10. Facade.jpg -------------------------------------------------------------------------------- /readme/images/11. Flyweight example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/11. Flyweight example.jpg -------------------------------------------------------------------------------- /readme/images/11. Flyweight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/11. Flyweight.jpg -------------------------------------------------------------------------------- /readme/images/12. Proxy example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/12. Proxy example.jpg -------------------------------------------------------------------------------- /readme/images/12. Proxy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/12. Proxy.jpg -------------------------------------------------------------------------------- /readme/images/13. Mediator example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/13. Mediator example.jpg -------------------------------------------------------------------------------- /readme/images/13. Mediator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/13. Mediator.jpg -------------------------------------------------------------------------------- /readme/images/14. Iterator example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/14. Iterator example.jpg -------------------------------------------------------------------------------- /readme/images/14. Iterator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/14. Iterator.jpg -------------------------------------------------------------------------------- /readme/images/15. Memento example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/15. Memento example.jpg -------------------------------------------------------------------------------- /readme/images/15. Memento.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/15. Memento.jpg -------------------------------------------------------------------------------- /readme/images/16. Strategy example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/16. Strategy example.jpg -------------------------------------------------------------------------------- /readme/images/16. Strategy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/16. Strategy.jpg -------------------------------------------------------------------------------- /readme/images/17. Command example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/17. Command example.jpg -------------------------------------------------------------------------------- /readme/images/17. Command.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/17. Command.jpg -------------------------------------------------------------------------------- /readme/images/18. Observer example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/18. Observer example.jpg -------------------------------------------------------------------------------- /readme/images/18. Observer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/18. Observer.jpg -------------------------------------------------------------------------------- /readme/images/19. Visitor example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/19. Visitor example.jpg -------------------------------------------------------------------------------- /readme/images/19. Visitor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/19. Visitor.jpg -------------------------------------------------------------------------------- /readme/images/20. State example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/20. State example.jpg -------------------------------------------------------------------------------- /readme/images/20. State.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/20. State.jpg -------------------------------------------------------------------------------- /readme/images/21. Template Method example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/21. Template Method example.jpg -------------------------------------------------------------------------------- /readme/images/21. Template Method.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/21. Template Method.jpg -------------------------------------------------------------------------------- /readme/images/22. Chain Of Responsibility example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/22. Chain Of Responsibility example.jpg -------------------------------------------------------------------------------- /readme/images/22. Chain Of Responsibility.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/22. Chain Of Responsibility.jpg -------------------------------------------------------------------------------- /readme/images/23. Interpreter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/readme/images/23. Interpreter.jpg -------------------------------------------------------------------------------- /setup-jest.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | 3 | /* global mocks for jsdom */ 4 | const mock = () => { 5 | let storage: { [key: string]: string } = {}; 6 | return { 7 | getItem: (key: string) => (key in storage ? storage[key] : null), 8 | setItem: (key: string, value: string) => (storage[key] = value || ''), 9 | removeItem: (key: string) => delete storage[key], 10 | clear: () => (storage = {}), 11 | }; 12 | }; 13 | 14 | Object.defineProperty(window, 'localStorage', { value: mock() }); 15 | Object.defineProperty(window, 'sessionStorage', { value: mock() }); 16 | Object.defineProperty(window, 'getComputedStyle', { 17 | value: () => ['-webkit-appearance'], 18 | }); 19 | 20 | Object.defineProperty(document.body.style, 'transform', { 21 | value: () => { 22 | return { 23 | enumerable: true, 24 | configurable: true, 25 | }; 26 | }, 27 | }); 28 | 29 | /* output shorter and more meaningful Zone error stack traces */ 30 | // Error.stackTraceLimit = 2; 31 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/abstract-factory.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {AbstractFactoryComponent} from './abstract-factory/abstract-factory.component'; 3 | import {AngularMaterialModule} from '../modules/angular-material.module'; 4 | import {AbstractFactoryRoutingModule} from './abstract-factory.routes'; 5 | import {FormsModule} from '@angular/forms'; 6 | import {CommonModule} from '@angular/common'; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | AbstractFactoryComponent 11 | ], 12 | imports: [ 13 | CommonModule, 14 | FormsModule, 15 | AngularMaterialModule, 16 | AbstractFactoryRoutingModule 17 | ] 18 | }) 19 | export class AbstractFactoryModule { } 20 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/abstract-factory.routes.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import {AbstractFactoryComponent} from './abstract-factory/abstract-factory.component'; 4 | 5 | const routes: Routes = [{ path: '', component: AbstractFactoryComponent }]; 6 | 7 | @NgModule({ 8 | imports: [RouterModule.forChild(routes)], 9 | exports: [RouterModule] 10 | }) 11 | export class AbstractFactoryRoutingModule { } 12 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/abstract-factory/abstract-factory.component.html: -------------------------------------------------------------------------------- 1 |
2 |
7 |

8 | Abstract Factory Pattern 9 |

10 | 11 |
12 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 13 |
14 | 15 | 16 | Theme selection 17 | 18 | 19 | {{theme.name}} 20 | 21 | 22 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/abstract-factory/abstract-factory.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | 5 | div.light { 6 | background-color: white; 7 | color: black; 8 | } 9 | 10 | div.dark { 11 | background-color: #616161; 12 | color: white; 13 | } 14 | 15 | div.personal { 16 | background-color: #e0e0e0; 17 | color: #ff6e40; 18 | } 19 | 20 | mat-form-field { 21 | margin-top: 30px; 22 | } 23 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/abstract-factory/abstract-factory.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AbstractTheme, Theme } from '../models/theme.model'; 3 | import { DarkThemeFactory, LightThemeFactory, PersonalThemeFactory } from '../models/factory.model'; 4 | 5 | @Component({ 6 | selector: 'app-abstract-factory', 7 | templateUrl: './abstract-factory.component.html', 8 | styleUrls: ['./abstract-factory.component.scss'] 9 | }) 10 | export class AbstractFactoryComponent implements OnInit { 11 | private readonly _themes: AbstractTheme[]; 12 | public get themes(): AbstractTheme[] { 13 | return this._themes; 14 | } 15 | public selectedTheme: AbstractTheme; 16 | 17 | constructor() { 18 | this._themes = new Array(); 19 | } 20 | 21 | ngOnInit(): void { 22 | // I split this up for better readability 23 | const lightTheme: AbstractTheme = new Theme(new LightThemeFactory(), 'Light theme'); 24 | this._themes.push(lightTheme); 25 | const darkTheme: AbstractTheme = new Theme(new DarkThemeFactory(), 'Dark theme'); 26 | this._themes.push(darkTheme); 27 | const personalTheme: AbstractTheme = new Theme(new PersonalThemeFactory(), 'Personal theme'); 28 | this._themes.push(personalTheme); 29 | 30 | this.selectedTheme = this._themes[0]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/models/factory.model.ts: -------------------------------------------------------------------------------- 1 | import { AbstractStyle, DarkThemeStyle, LightThemeStyle, PersonalThemeStyle } from './style.model'; 2 | import { AbstractFont, DarkThemeFont, LightThemeFont, PersonalThemeFont } from './font.model'; 3 | 4 | export interface AbstractFactory { 5 | createStyle(): AbstractStyle; 6 | createFont(): AbstractFont; 7 | } 8 | 9 | export class DarkThemeFactory implements AbstractFactory { 10 | public createStyle(): AbstractStyle { 11 | return new DarkThemeStyle(); 12 | } 13 | 14 | public createFont(): AbstractFont { 15 | return new DarkThemeFont(); 16 | } 17 | } 18 | 19 | export class LightThemeFactory implements AbstractFactory { 20 | public createStyle(): AbstractStyle { 21 | return new LightThemeStyle(); 22 | } 23 | 24 | public createFont(): AbstractFont { 25 | return new LightThemeFont(); 26 | } 27 | } 28 | 29 | export class PersonalThemeFactory implements AbstractFactory { 30 | public createStyle(): AbstractStyle { 31 | return new PersonalThemeStyle(); 32 | } 33 | 34 | public createFont(): AbstractFont { 35 | return new PersonalThemeFont(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/models/font.model.ts: -------------------------------------------------------------------------------- 1 | export interface AbstractFont { 2 | getFontName(): string; 3 | } 4 | 5 | export class DarkThemeFont implements AbstractFont { 6 | public getFontName(): string { 7 | return 'Arial Black'; 8 | } 9 | } 10 | 11 | export class LightThemeFont implements AbstractFont { 12 | public getFontName(): string { 13 | return 'Comic Sans MS'; 14 | } 15 | } 16 | 17 | export class PersonalThemeFont implements AbstractFont { 18 | public getFontName(): string { 19 | return 'Times New Roman'; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/models/style.model.ts: -------------------------------------------------------------------------------- 1 | export interface AbstractStyle { 2 | getStyleName(): string; 3 | } 4 | 5 | export class DarkThemeStyle implements AbstractStyle { 6 | public getStyleName(): string { 7 | return 'dark'; 8 | } 9 | } 10 | 11 | export class LightThemeStyle implements AbstractStyle { 12 | public getStyleName(): string { 13 | return 'light'; 14 | } 15 | } 16 | 17 | export class PersonalThemeStyle implements AbstractStyle { 18 | public getStyleName(): string { 19 | return 'personal'; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/01. Abstract Factory/models/theme.model.ts: -------------------------------------------------------------------------------- 1 | import { AbstractFactory } from './factory.model'; 2 | import { AbstractStyle } from './style.model'; 3 | import { AbstractFont } from './font.model'; 4 | 5 | // Client 6 | export interface AbstractTheme { 7 | name: string; 8 | getStyleName(): string; 9 | getFontName(): string; 10 | } 11 | 12 | export class Theme implements AbstractTheme { 13 | public name: string; 14 | private style: AbstractStyle; 15 | private font: AbstractFont; 16 | 17 | constructor(factory: AbstractFactory, name: string) { 18 | this.name = name; 19 | this.style = factory.createStyle(); 20 | this.font = factory.createFont(); 21 | } 22 | 23 | public getStyleName(): string { 24 | return this.style.getStyleName(); 25 | } 26 | 27 | public getFontName(): string { 28 | return this.font.getFontName(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/02. Singleton/models/random.utils.ts: -------------------------------------------------------------------------------- 1 | // resource: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Math/math.random 2 | 3 | export function getRandomInt(max: number): number { 4 | return Math.floor(Math.random() * Math.floor(max)); 5 | } 6 | -------------------------------------------------------------------------------- /src/app/02. Singleton/singleton.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {SingletonComponent} from './singleton/singleton.component'; 3 | import {SingletonRoutingModule} from './singleton.routes'; 4 | import {AngularMaterialModule} from "../modules/angular-material.module"; 5 | 6 | @NgModule({ 7 | declarations : [ 8 | SingletonComponent 9 | ], 10 | imports: [ 11 | SingletonRoutingModule, 12 | AngularMaterialModule 13 | ] 14 | }) 15 | export class SingletonModule { } 16 | -------------------------------------------------------------------------------- /src/app/02. Singleton/singleton.routes.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { SingletonComponent } from './singleton/singleton.component'; 4 | 5 | const routes: Routes = [{ path: '', component: SingletonComponent }]; 6 | 7 | @NgModule({ 8 | imports: [RouterModule.forChild(routes)], 9 | exports: [RouterModule] 10 | }) 11 | export class SingletonRoutingModule { } 12 | -------------------------------------------------------------------------------- /src/app/02. Singleton/singleton/singleton.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

4 | Singleton Pattern 5 |

6 |
7 | id stays the same, because we don't create a new instance. If you reload the page, there would be a new instance, because the component (parent of teas) is destroyed and initialized 8 |
9 |
10 | 11 | 12 | {{ blackTea.getType() }} 13 | 14 | 15 |
id: {{ blackTea.getId() }}
16 |
17 | 18 | 19 | 20 |
21 | 22 | 23 | {{ fruitTea.getType() }} 24 | 25 | 26 |
id: {{ fruitTea.getId() }}
27 |
28 | 29 | 30 | 31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /src/app/02. Singleton/singleton/singleton.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/02. Singleton/singleton/singleton.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AbstractTea, BlackTea, FruitTea } from '../models/tea.model'; 3 | 4 | @Component({ 5 | selector: 'app-singleton', 6 | templateUrl: './singleton.component.html', 7 | styleUrls: ['./singleton.component.scss'] 8 | }) 9 | export class SingletonComponent { 10 | private _blackTea: AbstractTea; 11 | public get blackTea(): AbstractTea { 12 | return this._blackTea; 13 | } 14 | private _fruitTea: AbstractTea; 15 | public get fruitTea(): AbstractTea { 16 | return this._fruitTea; 17 | } 18 | 19 | constructor() { 20 | this._blackTea = BlackTea.getInstance(); 21 | this._fruitTea = FruitTea.getInstance(); 22 | } 23 | 24 | public btnGetNewBlackTeaInstance(): void { 25 | // id stays the same, because we don't create a new object 26 | this._blackTea = BlackTea.getInstance(); 27 | } 28 | 29 | public btnGetNewFruitTeaInstance(): void { 30 | // id stays the same, because we don't create a new object 31 | this._fruitTea = FruitTea.getInstance(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/app/03. Prototype/models/car.model.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from './engine.model'; 2 | 3 | export interface Prototype { 4 | name: string; 5 | color: string; 6 | clone(): Prototype; 7 | } 8 | 9 | export class CarPrototype implements Prototype { 10 | public name: string; 11 | public color: string; 12 | private engine: Engine; 13 | 14 | constructor(name: string, color: string, engine: Engine) { 15 | this.name = name; 16 | this.color = color; 17 | this.engine = engine; 18 | } 19 | 20 | public clone(): Prototype { 21 | // https://stackoverflow.com/a/53442750/14427814 22 | return Object.assign(Object.create(this), this); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/app/03. Prototype/models/engine.model.ts: -------------------------------------------------------------------------------- 1 | export interface Engine { 2 | ccm: number; 3 | fuel: string; 4 | } 5 | 6 | export class PetrolEngine implements Engine { 7 | public fuel = 'petrol'; 8 | public ccm: number; 9 | 10 | constructor(ccm: number) { 11 | this.ccm = ccm; 12 | } 13 | } 14 | 15 | export class DieselEngine implements Engine { 16 | public fuel = 'diesel'; 17 | public ccm: number; 18 | 19 | constructor(ccm: number) { 20 | this.ccm = ccm; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/03. Prototype/prototype.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { PrototypeComponent } from './prototype/prototype.component'; 3 | import { PrototypeRoutingModule } from './prototype.routes'; 4 | import {AngularMaterialModule} from '../modules/angular-material.module'; 5 | import {CommonModule} from '@angular/common'; 6 | import {FormsModule} from '@angular/forms'; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | PrototypeComponent 11 | ], 12 | imports: [ 13 | PrototypeRoutingModule, 14 | AngularMaterialModule, 15 | CommonModule, 16 | FormsModule 17 | ] 18 | }) 19 | export class PrototypeModule {} 20 | -------------------------------------------------------------------------------- /src/app/03. Prototype/prototype.routes.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { PrototypeComponent } from './prototype/prototype.component'; 4 | 5 | const routes: Routes = [{ path: '', component: PrototypeComponent }]; 6 | 7 | @NgModule({ 8 | imports: [RouterModule.forChild(routes)], 9 | exports: [RouterModule] 10 | }) 11 | export class PrototypeRoutingModule { } 12 | -------------------------------------------------------------------------------- /src/app/03. Prototype/prototype/prototype.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Prototype Pattern (Clone) 4 |

5 | 6 | 7 | Cars 8 | 9 | 10 | 11 | Favorite food 12 | 13 | red 14 | blue 15 | green 16 | black 17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 | {{ car.name }} with {{car.color}} color 25 |
26 |
27 |
28 | 29 |
30 |
31 | -------------------------------------------------------------------------------- /src/app/03. Prototype/prototype/prototype.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | 5 | mat-card-actions { 6 | display: flex; 7 | flex-direction: row; 8 | justify-content: center; 9 | padding: 0; 10 | } 11 | 12 | button { 13 | height: 50px; 14 | } 15 | 16 | div.container { 17 | display: flex; 18 | flex-direction: column; 19 | align-items: center; 20 | } 21 | 22 | mat-card { 23 | margin: 15px; 24 | max-width: 400px; 25 | } 26 | -------------------------------------------------------------------------------- /src/app/03. Prototype/prototype/prototype.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { CarPrototype, Prototype } from '../models/car.model'; 3 | import { Engine, PetrolEngine } from '../models/engine.model'; 4 | 5 | @Component({ 6 | selector: 'app-prototype', 7 | templateUrl: './prototype.component.html', 8 | styleUrls: ['./prototype.component.scss'] 9 | }) 10 | export class PrototypeComponent implements OnInit { 11 | private readonly _cars: Prototype[]; 12 | public get cars(): Prototype[] { 13 | return this._cars; 14 | } 15 | public selectedColor: string; 16 | 17 | constructor() { 18 | this._cars = new Array(); 19 | } 20 | 21 | ngOnInit(): void { 22 | const engine: Engine = new PetrolEngine(2000); 23 | this._cars.push(new CarPrototype('Toyota', 'red', engine)); 24 | this.selectedColor = 'red'; 25 | } 26 | 27 | btnCopyLastCarWithNewColor(): void { 28 | const newCar: Prototype = this._cars[this._cars.length - 1].clone(); 29 | newCar.color = this.selectedColor; 30 | this._cars.push(newCar); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/04. Builder/builder-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { BuilderComponent } from './builder/builder.component'; 5 | 6 | const routes: Routes = [{ path: '', component: BuilderComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class BuilderRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/04. Builder/builder.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { BuilderRoutingModule } from './builder-routing.module'; 5 | import { BuilderComponent } from './builder/builder.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [BuilderComponent], 11 | imports: [ 12 | CommonModule, 13 | BuilderRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class BuilderModule { } 18 | -------------------------------------------------------------------------------- /src/app/04. Builder/builder/builder.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Builder Pattern 4 |

5 |
6 | 7 | House {{i+1}} 8 | 9 |
walls: {{house.walls}}
10 |
doors: {{house.doors}}
11 |
windows: {{house.windows}}
12 |
garden: {{house.garden}}
13 |
pool: {{house.pool}}
14 |
floors: {{house.floors}}
15 |
basement: {{house.basement}}
16 |
17 |
18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /src/app/04. Builder/builder/builder.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | 5 | div.container { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | } 10 | 11 | div.content { 12 | display: flex; 13 | flex-direction: row; 14 | } 15 | 16 | mat-card { 17 | margin: 15px; 18 | max-width: 300px; 19 | } 20 | -------------------------------------------------------------------------------- /src/app/04. Builder/builder/builder.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { AngularMaterialModule } from '../../modules/angular-material.module'; 3 | import { BuilderComponent } from './builder.component'; 4 | import { House, HouseImpl } from '../models/house.model'; 5 | 6 | describe('BuilderComponent', () => { 7 | let component: BuilderComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async () => { 11 | await TestBed.configureTestingModule({ 12 | declarations: [BuilderComponent], 13 | imports: [AngularMaterialModule] 14 | }).compileComponents(); 15 | }); 16 | 17 | beforeEach(() => { 18 | fixture = TestBed.createComponent(BuilderComponent); 19 | component = fixture.componentInstance; 20 | fixture.detectChanges(); 21 | }); 22 | 23 | it('should have house 1', () => { 24 | const house1: House = component.houses[0]; 25 | expect(house1.basement).toEqual(true); 26 | expect(house1.floors).toEqual(2); 27 | expect(house1.pool).toEqual(false); 28 | expect(house1.garden).toEqual(true); 29 | expect(house1.walls).toEqual(17); 30 | expect(house1.windows).toEqual(32); 31 | expect(house1.doors).toEqual(7); 32 | }); 33 | 34 | it('should have house 2', () => { 35 | const house2: House = component.houses[1]; 36 | expect(house2.basement).toEqual(true); 37 | expect(house2.floors).toEqual(7); 38 | expect(house2.pool).toEqual(true); 39 | expect(house2.garden).toEqual(true); 40 | expect(house2.walls).toEqual(42); 41 | expect(house2.windows).toEqual(75); 42 | expect(house2.doors).toEqual(15); 43 | }); 44 | 45 | it('should have a default house', () => { 46 | const house2: House = new HouseImpl(); 47 | expect(house2.basement).toEqual(false); 48 | expect(house2.floors).toEqual(0); 49 | expect(house2.pool).toEqual(false); 50 | expect(house2.garden).toEqual(false); 51 | expect(house2.walls).toEqual(0); 52 | expect(house2.windows).toEqual(0); 53 | expect(house2.doors).toEqual(0); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /src/app/04. Builder/builder/builder.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {HouseBuilder} from '../models/builder.model'; 3 | import {Director} from '../models/director.model'; 4 | import {House} from '../models/house.model'; 5 | 6 | @Component({ 7 | selector: 'app-builder', 8 | templateUrl: './builder.component.html', 9 | styleUrls: ['./builder.component.scss'] 10 | }) 11 | export class BuilderComponent implements OnInit { 12 | 13 | private readonly _houses: House[]; 14 | public get houses(): House[] { 15 | return this._houses; 16 | } 17 | 18 | constructor() { 19 | this._houses = new Array(); 20 | } 21 | 22 | ngOnInit(): void { 23 | const builder = new HouseBuilder(); 24 | const director = new Director(); 25 | director.setBuilder(builder); 26 | 27 | director.constructFamilyHouse(); 28 | const familyHouse = builder.getResult(); 29 | this._houses.push(familyHouse); 30 | 31 | director.constructVilla(); 32 | const villa = builder.getResult(); 33 | this._houses.push(villa); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/04. Builder/models/builder.model.ts: -------------------------------------------------------------------------------- 1 | import { House, HouseImpl } from './house.model'; 2 | 3 | export interface Builder { 4 | buildWalls(count: number): void; 5 | buildDoors(count: number): void; 6 | buildWindows(count: number): void; 7 | buildGarden(): void; 8 | buildPool(): void; 9 | buildFloors(count: number): void; 10 | buildBasement(): void; 11 | getResult(): House; 12 | } 13 | 14 | export class HouseBuilder implements Builder { 15 | private house: House; 16 | 17 | constructor() { 18 | this.reset(); 19 | } 20 | 21 | private reset(): void { 22 | this.house = new HouseImpl(); 23 | } 24 | 25 | // e.g. buildPartA 26 | public buildWalls(count: number): void { 27 | this.house.walls = count; 28 | } 29 | 30 | // e.g. buildPartB 31 | public buildDoors(count: number): void { 32 | this.house.doors = count; 33 | } 34 | 35 | // e.g. buildPartC 36 | public buildWindows(count: number): void { 37 | this.house.windows = count; 38 | } 39 | 40 | public buildGarden(): void { 41 | this.house.garden = true; 42 | } 43 | 44 | public buildPool(): void { 45 | this.house.pool = true; 46 | } 47 | 48 | public buildFloors(count: number): void { 49 | this.house.floors = count; 50 | } 51 | 52 | public buildBasement(): void { 53 | this.house.basement = true; 54 | } 55 | 56 | public getResult(): House { 57 | const result = this.house; 58 | this.reset(); 59 | return result; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/app/04. Builder/models/director.model.ts: -------------------------------------------------------------------------------- 1 | import { Builder } from './builder.model'; 2 | 3 | export class Director { 4 | private builder: Builder; 5 | 6 | public setBuilder(builder: Builder): void { 7 | this.builder = builder; 8 | } 9 | 10 | public constructVilla(): void { 11 | this.builder.buildWalls(42); 12 | this.builder.buildBasement(); 13 | this.builder.buildDoors(15); 14 | this.builder.buildFloors(7); 15 | this.builder.buildGarden(); 16 | this.builder.buildPool(); 17 | this.builder.buildWindows(75); 18 | } 19 | 20 | public constructFamilyHouse(): void { 21 | this.builder.buildWalls(17); 22 | this.builder.buildBasement(); 23 | this.builder.buildWindows(32); 24 | this.builder.buildDoors(7); 25 | this.builder.buildFloors(2); 26 | this.builder.buildGarden(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/04. Builder/models/house.model.ts: -------------------------------------------------------------------------------- 1 | export interface House { 2 | walls: number; 3 | doors: number; 4 | windows: number; 5 | garden: boolean; 6 | pool: boolean; 7 | floors: number; 8 | basement: boolean; 9 | } 10 | 11 | export class HouseImpl implements House { 12 | constructor() { 13 | this.walls = 0; 14 | this.doors = 0; 15 | this.windows = 0; 16 | this.garden = false; 17 | this.pool = false; 18 | this.floors = 0; 19 | this.basement = false; 20 | } 21 | public walls: number; 22 | public doors: number; 23 | public windows: number; 24 | public garden: boolean; 25 | public pool: boolean; 26 | public floors: number; 27 | public basement: boolean; 28 | } 29 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/factory-method-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { FactoryMethodComponent } from './factory-method/factory-method.component'; 5 | 6 | const routes: Routes = [{ path: '', component: FactoryMethodComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class FactoryMethodRoutingModule { } 13 | 14 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/factory-method.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { FactoryMethodRoutingModule } from './factory-method-routing.module'; 5 | import { FactoryMethodComponent } from './factory-method/factory-method.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [FactoryMethodComponent], 11 | imports: [ 12 | CommonModule, 13 | FactoryMethodRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class FactoryMethodModule { } 18 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/factory-method/factory-method.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Factory Method Pattern (Virtual Constructor) 4 |

5 | 6 | 7 | Food planning 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | {{ currentMeal.activity }} 17 |
18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/factory-method/factory-method.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | 5 | div.container { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | } 10 | 11 | mat-card { 12 | margin: 15px; 13 | max-width: 300px; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/factory-method/factory-method.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { clientCode } from '../models/client.utils'; 3 | import { PizzaCreator, TackoCreator, WrapCreator } from '../models/creator.model'; 4 | import {FoodPlanningHistory} from '../models/food-planning-history.model'; 5 | 6 | @Component({ 7 | selector: 'app-factory-method', 8 | templateUrl: './factory-method.component.html', 9 | styleUrls: ['./factory-method.component.scss'] 10 | }) 11 | export class FactoryMethodComponent { 12 | private readonly _foodPlanning: FoodPlanningHistory[]; 13 | public get foodPlanning(): FoodPlanningHistory[] { 14 | return this._foodPlanning; 15 | } 16 | 17 | constructor() { 18 | this._foodPlanning = new Array(); 19 | } 20 | 21 | public trackByFn(index, item: FoodPlanningHistory): number { 22 | return item.index; 23 | } 24 | 25 | public btnEatPizza(): void { 26 | const activity: string = clientCode(new PizzaCreator()); 27 | this.addActivityToHistory(activity); 28 | } 29 | 30 | public btnEatWrap(): void { 31 | const activity: string = clientCode(new WrapCreator()); 32 | this.addActivityToHistory(activity); 33 | } 34 | 35 | public btnEatTacko(): void { 36 | const activity: string = clientCode(new TackoCreator()); 37 | this.addActivityToHistory(activity); 38 | } 39 | 40 | private addActivityToHistory(activity: string) { 41 | this._foodPlanning.push(new FoodPlanningHistory(this._foodPlanning.length, activity)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/models/client.utils.ts: -------------------------------------------------------------------------------- 1 | import { Creator } from './creator.model'; 2 | 3 | export function clientCode(creator: Creator): string { 4 | return creator.produceAndEat(); 5 | } 6 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/models/creator.model.ts: -------------------------------------------------------------------------------- 1 | import { Food, Pizza, Tacko, Wrap } from './food.model'; 2 | 3 | export abstract class Creator { 4 | public abstract factoryMethodForFood(): Food; 5 | 6 | public produceAndEat(): string { 7 | const food = this.factoryMethodForFood(); 8 | const produce: string = food.produce(); 9 | const eat: string = food.eat(); 10 | return `${produce} and ${eat}`; 11 | } 12 | } 13 | 14 | export class PizzaCreator extends Creator { 15 | public factoryMethodForFood(): Food { 16 | return new Pizza(); 17 | } 18 | } 19 | 20 | export class WrapCreator extends Creator { 21 | public factoryMethodForFood(): Food { 22 | return new Wrap(); 23 | } 24 | } 25 | 26 | export class TackoCreator extends Creator { 27 | public factoryMethodForFood(): Food { 28 | return new Tacko(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/models/food-planning-history.model.ts: -------------------------------------------------------------------------------- 1 | export class FoodPlanningHistory { 2 | index: number; 3 | activity: string; 4 | 5 | constructor(index: number, activity: string) { 6 | this.index = index; 7 | this.activity = activity; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/05. Factory Method/models/food.model.ts: -------------------------------------------------------------------------------- 1 | export interface Food { 2 | produce(): string; 3 | eat(): string; 4 | } 5 | 6 | export class Pizza implements Food { 7 | public produce(): string { 8 | return 'Let`s make Pizza.'; 9 | } 10 | 11 | public eat(): string { 12 | return 'Let`s eat Pizza.'; 13 | } 14 | } 15 | 16 | export class Wrap implements Food { 17 | public produce(): string { 18 | return 'Let`s make a Wrap.'; 19 | } 20 | 21 | public eat(): string { 22 | return 'Let`s eat a Wrap.'; 23 | } 24 | } 25 | 26 | export class Tacko implements Food { 27 | public produce(): string { 28 | return 'Let`s make a Tacko.'; 29 | } 30 | 31 | public eat(): string { 32 | return 'Let`s eat a Tacko.'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/06. Adapter/adapter-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { AdapterComponent } from './adapter/adapter.component'; 5 | 6 | const routes: Routes = [{ path: '', component: AdapterComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class AdapterRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/06. Adapter/adapter.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { AdapterRoutingModule } from './adapter-routing.module'; 5 | import { AdapterComponent } from './adapter/adapter.component'; 6 | import {AngularMaterialModule} from "../modules/angular-material.module"; 7 | 8 | 9 | @NgModule({ 10 | declarations: [AdapterComponent], 11 | imports: [ 12 | CommonModule, 13 | AdapterRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class AdapterModule { } 18 | -------------------------------------------------------------------------------- /src/app/06. Adapter/adapter/adapter.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Adapter Pattern (Wrapper) 4 |

5 |
6 | 7 | 8 | Cat 9 | 10 | 11 | It's only a cat 12 | 13 | 14 | 15 | 16 | 17 |
18 | {{ catSound }} 19 |
20 |
21 | 22 |
23 | 24 | 25 | Toy 26 | 27 | 28 | It's only a toy 29 | 30 | 31 | 32 | 33 | 34 |
35 | {{ toySound }} 36 |
37 |
38 | 39 |
40 | 41 | 42 | ToyCat (CatAdapter) 43 | 44 | 45 | It's a toy, but imitates a cat :O 46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 | {{ catAdapterSound }} 54 |
55 |
56 | 57 |
58 |
59 |
60 | -------------------------------------------------------------------------------- /src/app/06. Adapter/adapter/adapter.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/src/app/06. Adapter/adapter/adapter.component.scss -------------------------------------------------------------------------------- /src/app/06. Adapter/adapter/adapter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {Cat, NorwegianForest} from "../models/cat.model"; 3 | import {Toy, AnyToy} from "../models/toy.model"; 4 | import {CatAdapter} from "../models/cat.adapter"; 5 | 6 | @Component({ 7 | selector: 'app-adapter', 8 | templateUrl: './adapter.component.html', 9 | styleUrls: ['./adapter.component.scss'] 10 | }) 11 | export class AdapterComponent { 12 | public catSounds: string[]; 13 | public toySounds: string[]; 14 | public catAdapterSounds: string[]; 15 | 16 | private cat: Cat; // adaptee 17 | private toy: Toy; // target interface 18 | private catAdapter: Toy; // adapter 19 | 20 | constructor() { 21 | this.catSounds = []; 22 | this.toySounds = []; 23 | this.catAdapterSounds = []; 24 | 25 | this.client(); 26 | } 27 | 28 | public btnCatSound(): void { 29 | this.catSounds.push(this.cat.makeSound()); 30 | } 31 | 32 | public btnToySound(): void { 33 | this.toySounds.push(this.toy.squeak()); 34 | } 35 | 36 | public btnCatAdapterSound(): void { 37 | this.catAdapterSounds.push(this.catAdapter.squeak()); 38 | } 39 | 40 | private client(): void { 41 | 42 | // inspired by 43 | // https://www.geeksforgeeks.org/adapter-pattern/ 44 | 45 | this.cat = new NorwegianForest(); 46 | this.toy = new AnyToy(); 47 | this.catAdapter = new CatAdapter(this.cat); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/app/06. Adapter/models/cat.adapter.ts: -------------------------------------------------------------------------------- 1 | import { Toy } from './toy.model'; 2 | import { Cat } from './cat.model'; 3 | 4 | export class CatAdapter implements Toy { 5 | private cat: Cat; 6 | 7 | constructor(cat: Cat) { 8 | this.cat = cat; 9 | } 10 | 11 | public squeak(): string { 12 | return this.cat.makeSound(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/app/06. Adapter/models/cat.model.ts: -------------------------------------------------------------------------------- 1 | export interface Cat { 2 | hunt(): string; 3 | makeSound(): string; 4 | } 5 | 6 | // adaptee 7 | export class BritishShortHair implements Cat { 8 | public hunt(): string { 9 | return 'Hunting birds..'; 10 | } 11 | 12 | public makeSound(): string { 13 | return 'Miau.. Miau..'; 14 | } 15 | } 16 | 17 | export class NorwegianForest implements Cat { 18 | public hunt(): string { 19 | return 'Hunting fish..'; 20 | } 21 | 22 | public makeSound(): string { 23 | return 'Rrrroar.. Rrrroar..'; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/06. Adapter/models/toy.model.ts: -------------------------------------------------------------------------------- 1 | // target interface - toys dont hunt and only squeak 2 | export interface Toy { 3 | squeak(): string; 4 | } 5 | 6 | export class AnyToy implements Toy { 7 | public squeak(): string { 8 | return 'squeaaaaaak...'; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/app/07. Bridge/bridge-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { BridgeComponent } from './bridge/bridge.component'; 5 | 6 | const routes: Routes = [{ path: '', component: BridgeComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class BridgeRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/07. Bridge/bridge.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { BridgeRoutingModule } from './bridge-routing.module'; 5 | import { BridgeComponent } from './bridge/bridge.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [BridgeComponent], 11 | imports: [ 12 | CommonModule, 13 | BridgeRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class BridgeModule { } 18 | -------------------------------------------------------------------------------- /src/app/07. Bridge/bridge/bridge.component.scss: -------------------------------------------------------------------------------- 1 | button { 2 | margin-bottom: 5px; 3 | } 4 | 5 | button:last-child { 6 | margin-bottom: 0; 7 | } 8 | 9 | div { 10 | text-align: center; 11 | } 12 | 13 | mat-card-content { 14 | display: flex; 15 | flex-direction: column; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/07. Bridge/bridge/bridge.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {Device, Radio, TV} from '../models/device.model'; 3 | import {Abstraction, AdvancedRemoteControl, RefinedAbstraction, RemoteControl} from '../models/remote.model'; 4 | 5 | @Component({ 6 | selector: 'app-bridge', 7 | templateUrl: './bridge.component.html', 8 | styleUrls: ['./bridge.component.scss'] 9 | }) 10 | export class BridgeComponent { 11 | 12 | // inspired by https://refactoring.guru/design-patterns/bridge 13 | 14 | public tv: Device; 15 | public radio: Device; 16 | public remoteTV: Abstraction; 17 | public remoteRadio: RefinedAbstraction; 18 | 19 | constructor() { 20 | this.tv = new TV(); 21 | this.remoteTV = new RemoteControl(this.tv); 22 | this.radio = new Radio(); 23 | this.remoteRadio = new AdvancedRemoteControl(this.radio); 24 | } 25 | 26 | public btnTogglePower(remote: Abstraction): void { 27 | remote.togglePower(); 28 | } 29 | 30 | public btnVolumeDown(remote: Abstraction): void { 31 | remote.volumeDown(); 32 | } 33 | 34 | public btnVolumeUp(remote: Abstraction): void { 35 | remote.volumeUp(); 36 | } 37 | 38 | public btnChannelDown(remote: Abstraction): void { 39 | remote.channelDown(); 40 | } 41 | 42 | public btnChannelUp(remote: Abstraction): void { 43 | remote.channelUp(); 44 | } 45 | 46 | public btnMute(advancedRemoteControl: RefinedAbstraction): void { 47 | advancedRemoteControl.mute(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/app/07. Bridge/models/remote.model.ts: -------------------------------------------------------------------------------- 1 | import { Device } from './device.model'; 2 | 3 | export interface Abstraction { 4 | togglePower(): boolean; 5 | volumeDown(): number; 6 | volumeUp(): number; 7 | channelDown(): number; 8 | channelUp(): number; 9 | } 10 | 11 | export interface RefinedAbstraction extends Abstraction{ 12 | mute(): number; 13 | } 14 | 15 | // Abstraction 16 | export class RemoteControl implements Abstraction { 17 | protected device: Device; 18 | 19 | constructor(device: Device) { 20 | this.device = device; 21 | } 22 | 23 | public togglePower(): boolean { 24 | return this.device.isEnabled() ? this.device.disable() : this.device.enable(); 25 | } 26 | 27 | public volumeDown(): number { 28 | const currentVolume: number = this.device.getVolume(); 29 | return currentVolume >= 1 ? this.device.setVolume(currentVolume - 1) : this.device.setVolume(0); 30 | } 31 | 32 | public volumeUp(): number { 33 | const currentVolume: number = this.device.getVolume(); 34 | return currentVolume <= 99 ? this.device.setVolume(currentVolume + 1) : this.device.setVolume(100); 35 | } 36 | 37 | public channelDown(): number { 38 | const currentChannel: number = this.device.getChannel(); 39 | return currentChannel >= 1 ? this.device.setChannel(currentChannel - 1) : this.device.setChannel(0); 40 | } 41 | 42 | public channelUp(): number { 43 | const currentChannel: number = this.device.getChannel(); 44 | return currentChannel <= 99 ? this.device.setChannel(currentChannel + 1) : this.device.setChannel(0); 45 | } 46 | } 47 | 48 | export class AdvancedRemoteControl extends RemoteControl implements RefinedAbstraction { 49 | constructor(device: Device) { 50 | super(device); 51 | } 52 | 53 | public mute(): number { 54 | return this.device.setVolume(0); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/app/08. Composite/composite-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { CompositeComponent } from './composite/composite.component'; 5 | 6 | const routes: Routes = [{ path: '', component: CompositeComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class CompositeRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/08. Composite/composite.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { CompositeRoutingModule } from './composite-routing.module'; 5 | import { CompositeComponent } from './composite/composite.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | 8 | @NgModule({ 9 | declarations: [CompositeComponent], 10 | imports: [ 11 | CommonModule, 12 | CompositeRoutingModule, 13 | AngularMaterialModule 14 | ] 15 | }) 16 | export class CompositeModule { } 17 | -------------------------------------------------------------------------------- /src/app/08. Composite/composite/composite.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Composite Pattern (Object Tree) 4 |

5 |
6 | 7 | 8 | 9 | 10 | 11 | {{ saluteLog }} 12 | 13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /src/app/08. Composite/composite/composite.component.scss: -------------------------------------------------------------------------------- 1 | mat-card { 2 | margin: 15px; 3 | max-width: 400px; 4 | width: 400px; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/08. Composite/composite/composite.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Soldier } from '../models/soldier.model'; 3 | import { SoldierComposite } from '../models/soldier.composite'; 4 | import { SoldierLeaf } from '../models/soldier.leaf'; 5 | 6 | // Resource: https://refactoring.guru/design-patterns/composite/typescript/example 7 | @Component({ 8 | selector: 'app-composite', 9 | templateUrl: './composite.component.html', 10 | styleUrls: ['./composite.component.scss'] 11 | }) 12 | export class CompositeComponent { 13 | 14 | public saluteLog: string; 15 | 16 | public readonly general: SoldierComposite; 17 | private readonly officer1: SoldierComposite; 18 | private readonly officer2: SoldierComposite; 19 | private readonly officer3: SoldierComposite; 20 | 21 | constructor() { 22 | this.general = new SoldierComposite('Keanu Reeves'); 23 | 24 | this.officer1 = new SoldierComposite('Hiroyuki Sanada'); 25 | this.addSoldierLeafs(this.officer1, 1, 12); 26 | this.general.add(this.officer1); 27 | 28 | this.officer2 = new SoldierComposite('Tadanobu Asano'); 29 | this.addSoldierLeafs(this.officer2, 13, 30); 30 | this.general.add(this.officer2); 31 | 32 | this.officer3 = new SoldierComposite('Jin Akanishi'); 33 | this.addSoldierLeafs(this.officer3, 31, 43); 34 | this.general.add(this.officer3); 35 | } 36 | 37 | private addSoldierLeafs(soldier: SoldierComposite, start: number, end: number): void { 38 | for (let i = start; i <= end; i++) { 39 | soldier.add(new SoldierLeaf('Soldier ' + i.toString())); 40 | } 41 | } 42 | 43 | public btnSaluteToGeneral(): void { 44 | this.saluteLog = this.general.salute(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/app/08. Composite/models/soldier.composite.ts: -------------------------------------------------------------------------------- 1 | import { Soldier } from './soldier.model'; 2 | 3 | // Composite 4 | export class SoldierComposite extends Soldier { 5 | protected children: Soldier[] = []; 6 | 7 | constructor(name: string) { 8 | super(name); 9 | } 10 | 11 | public add(component: Soldier): void { 12 | this.children.push(component); 13 | component.setParent(this); 14 | } 15 | 16 | public remove(component: Soldier): void { 17 | const componentIndex = this.children.indexOf(component); 18 | this.children.splice(componentIndex, 1); 19 | component.setParent(null); 20 | } 21 | 22 | public isComposite(): boolean { 23 | return true; 24 | } 25 | 26 | public salute(): string { 27 | const results: string[] = []; 28 | 29 | results.push('>>>' + this.name + ' arrives <<<'); 30 | 31 | for (const child of this.children) { 32 | results.push(child.salute()); 33 | } 34 | 35 | return results.join(' | \n'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/app/08. Composite/models/soldier.leaf.ts: -------------------------------------------------------------------------------- 1 | import { Soldier } from './soldier.model'; 2 | 3 | // Leaf 4 | export class SoldierLeaf extends Soldier { 5 | constructor(name: string) { 6 | super(name); 7 | } 8 | public salute(): string { 9 | return this.name + ' salutes..!'; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/app/08. Composite/models/soldier.model.ts: -------------------------------------------------------------------------------- 1 | // Component 2 | export abstract class Soldier { 3 | protected parent: Soldier; 4 | protected name: string; 5 | 6 | protected constructor(name: string) { 7 | this.name = name; 8 | } 9 | 10 | public setParent(parent: Soldier): void { 11 | this.parent = parent; 12 | } 13 | 14 | public getParent(): Soldier { 15 | return this.parent; 16 | } 17 | 18 | public add(soldier: Soldier): void { 19 | // beneficial to define the child-management operations 20 | } 21 | 22 | public remove(soldier: Soldier): void { 23 | // beneficial to define the child-management operations 24 | } 25 | 26 | public isComposite(): boolean { 27 | return false; 28 | } 29 | 30 | public abstract salute(): string; 31 | } 32 | -------------------------------------------------------------------------------- /src/app/09. Decorator/decorator-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { DecoratorComponent } from './decorator/decorator.component'; 5 | 6 | const routes: Routes = [{ path: '', component: DecoratorComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class DecoratorRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/09. Decorator/decorator.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { DecoratorRoutingModule } from './decorator-routing.module'; 5 | import { DecoratorComponent } from './decorator/decorator.component'; 6 | import { AngularMaterialModule } from '../modules/angular-material.module'; 7 | import { FormsModule } from '@angular/forms'; 8 | 9 | @NgModule({ 10 | declarations: [DecoratorComponent], 11 | imports: [CommonModule, DecoratorRoutingModule, AngularMaterialModule, FormsModule] 12 | }) 13 | export class DecoratorModule {} 14 | -------------------------------------------------------------------------------- /src/app/09. Decorator/decorator/decorator.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Decorator Pattern (Wrapper) 4 |

5 |
6 | 7 | 8 | Pizza Calculator 9 | 10 | 11 | Current price: {{ price }} 12 | 13 | 14 | 15 | 16 | 19 | 20 |
{{ pizza.getTopping() }}
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | {{ topping }} 36 |
37 |
38 |
39 |
40 |
41 | -------------------------------------------------------------------------------- /src/app/09. Decorator/decorator/decorator.component.scss: -------------------------------------------------------------------------------- 1 | button { 2 | margin-top: 5px !important; 3 | } 4 | 5 | label { 6 | margin-bottom: 15px; 7 | } 8 | 9 | mat-card { 10 | max-width: 400px; 11 | } 12 | 13 | mat-card-content { 14 | display: flex; 15 | flex-direction: column; 16 | padding-top: 15px; 17 | align-items: center; 18 | } 19 | 20 | mat-radio-group { 21 | display: flex; 22 | } 23 | 24 | .mat-radio-button ~ .mat-radio-button { 25 | margin-left: 16px; 26 | } 27 | -------------------------------------------------------------------------------- /src/app/09. Decorator/models/extend-topping.decorator.ts: -------------------------------------------------------------------------------- 1 | import { ExtraCheeseToppingDecorator, JalapenoToppingDecorator } from './topping.decorator'; 2 | import { Pizza } from './pizza.model'; 3 | 4 | export class ExtraExtraCheeseToppingDecorator extends ExtraCheeseToppingDecorator implements Pizza { 5 | constructor(pizzaToDecorate: Pizza) { 6 | super(pizzaToDecorate); 7 | } 8 | 9 | public getPrice(): number { 10 | return super.getPrice() + 0.5; 11 | } 12 | 13 | public getTopping(): string { 14 | return super.getTopping() + ' & with moooore extra cheese'; 15 | } 16 | } 17 | 18 | export class HotJalapenoToppingDecorator extends JalapenoToppingDecorator implements Pizza { 19 | constructor(pizzaToDecorate: Pizza) { 20 | super(pizzaToDecorate); 21 | } 22 | 23 | public getPrice(): number { 24 | return super.getPrice() + 0.7; 25 | } 26 | 27 | public getTopping(): string { 28 | return super.getTopping() + ' & with extra hot hot jalapeno'; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/09. Decorator/models/pizza.model.ts: -------------------------------------------------------------------------------- 1 | // inspired by https://stackoverflow.com/a/2707425 2 | 3 | export interface Pizza { 4 | getPrice(): number; 5 | getTopping(): string; 6 | } 7 | 8 | class BasePizza implements Pizza { 9 | protected price: number; 10 | protected topping: string; 11 | 12 | public getPrice(): number { 13 | return this.price; 14 | } 15 | 16 | public getTopping(): string { 17 | return this.topping; 18 | } 19 | } 20 | 21 | export class Margherita extends BasePizza implements Pizza { 22 | constructor() { 23 | super(); 24 | this.price = 5.95; 25 | this.topping = 'Pizza Margherita'; 26 | } 27 | } 28 | 29 | export class Detroit extends BasePizza implements Pizza { 30 | constructor() { 31 | super(); 32 | this.price = 7.99; 33 | this.topping = 'Pizza Detroit'; 34 | } 35 | } 36 | 37 | export class Fugazzeta extends BasePizza implements Pizza { 38 | constructor() { 39 | super(); 40 | this.price = 6.89; 41 | this.topping = 'Pizza Fugazzeta'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/09. Decorator/models/topping.decorator.ts: -------------------------------------------------------------------------------- 1 | import { Pizza } from './pizza.model'; 2 | 3 | export class ExtraCheeseToppingDecorator implements Pizza { 4 | protected readonly priceCheese: number = 1.3; 5 | protected pizza: Pizza; 6 | 7 | constructor(pizzaToDecorate: Pizza) { 8 | this.pizza = pizzaToDecorate; 9 | } 10 | 11 | public getPrice(): number { 12 | return this.pizza.getPrice() + this.priceCheese; 13 | } 14 | 15 | public getTopping(): string { 16 | return this.pizza.getTopping() + '.. with extra cheese'; 17 | } 18 | } 19 | 20 | export class MushroomToppingDecorator implements Pizza { 21 | protected readonly priceMushrooms: number = 0.9; 22 | protected pizza: Pizza; 23 | 24 | constructor(pizzaToDecorate: Pizza) { 25 | this.pizza = pizzaToDecorate; 26 | } 27 | 28 | public getPrice(): number { 29 | return this.pizza.getPrice() + this.priceMushrooms; 30 | } 31 | 32 | public getTopping(): string { 33 | return this.pizza.getTopping() + '.. with extra mushrooms'; 34 | } 35 | } 36 | 37 | export class JalapenoToppingDecorator implements Pizza { 38 | protected readonly priceJalapeno: number = 1.5; 39 | protected pizza: Pizza; 40 | 41 | constructor(pizzaToDecorate: Pizza) { 42 | this.pizza = pizzaToDecorate; 43 | } 44 | 45 | public getPrice(): number { 46 | return this.pizza.getPrice() + this.priceJalapeno; 47 | } 48 | 49 | public getTopping(): string { 50 | return this.pizza.getTopping() + '.. with extra jalapeno'; 51 | } 52 | 53 | public extraHot(): number { 54 | return 0.8; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/app/10. Facade/facade-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { FacadeComponent } from './facade/facade.component'; 5 | 6 | const routes: Routes = [{ path: '', component: FacadeComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class FacadeRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/10. Facade/facade.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { FacadeRoutingModule } from './facade-routing.module'; 5 | import { FacadeComponent } from './facade/facade.component'; 6 | import {AngularMaterialModule} from "../modules/angular-material.module"; 7 | 8 | 9 | @NgModule({ 10 | declarations: [FacadeComponent], 11 | imports: [ 12 | CommonModule, 13 | FacadeRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class FacadeModule { } 18 | -------------------------------------------------------------------------------- /src/app/10. Facade/facade/facade.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Facade Pattern 4 |

5 |
6 | 7 | 8 | Coffee factory log 9 | 10 | 11 | 12 | 13 | 14 |
15 | {{ log }} 16 |
-------
17 |
18 |
19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /src/app/10. Facade/facade/facade.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | 5 | div.container { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | } 10 | 11 | div.content { 12 | display: flex; 13 | flex-direction: row; 14 | align-items: flex-start; 15 | } 16 | 17 | mat-card { 18 | margin: 15px; 19 | max-width: 300px; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/10. Facade/facade/facade.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CoffeeFacade, Facade } from "../models/facade.model"; 3 | 4 | @Component({ 5 | selector: 'app-facade', 6 | templateUrl: './facade.component.html', 7 | styleUrls: ['./facade.component.scss'] 8 | }) 9 | export class FacadeComponent { 10 | public logProduction: string[]; 11 | private facade: Facade; 12 | 13 | constructor() { 14 | this.facade = new CoffeeFacade(); 15 | this.logProduction = new Array(); 16 | } 17 | 18 | public btnProduceCoffee(): void { 19 | const log = this.facade.produce(); 20 | console.log(log); 21 | this.logProduction.push(log); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/app/10. Facade/models/drink.model.ts: -------------------------------------------------------------------------------- 1 | export interface Drink { 2 | cook(): string; 3 | } 4 | 5 | export class Coffee implements Drink { 6 | public cook(): string { 7 | return '[Drink]: cook coffee...'; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/10. Facade/models/facade.model.ts: -------------------------------------------------------------------------------- 1 | import { CoffeeTrader, Trader } from "./trader.model"; 2 | import { CoffeeMill, Mill } from "./mill.model"; 3 | import { Coffee, Drink } from "./drink.model"; 4 | 5 | export interface Facade { 6 | produce(): string; 7 | } 8 | 9 | export class CoffeeFacade implements Facade { 10 | protected trader: Trader; 11 | protected mill: Mill; 12 | protected drink: Drink; 13 | 14 | constructor(trader: Trader = null, 15 | mill: Mill = null, 16 | drink: Drink = null) { 17 | this.trader = trader || new CoffeeTrader(); 18 | this.mill = mill || new CoffeeMill(); 19 | this.drink = drink || new Coffee(); 20 | } 21 | 22 | public produce(): string { 23 | let result = '[Facade]: We need to produce coffee!! '; 24 | result += this.trader.getCoffee(); 25 | result += this.mill.grindCoffee(); 26 | result += this.drink.cook(); 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/app/10. Facade/models/mill.model.ts: -------------------------------------------------------------------------------- 1 | export interface Mill { 2 | grindCoffee(): string; 3 | } 4 | 5 | export class CoffeeMill implements Mill { 6 | public grindCoffee(): string { 7 | return '[Mill]: grind coffee... '; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/10. Facade/models/trader.model.ts: -------------------------------------------------------------------------------- 1 | export interface Trader { 2 | getCoffee(): string; 3 | } 4 | 5 | export class CoffeeTrader implements Trader { 6 | public getCoffee(): string { 7 | return '[Trader]: get coffee from Brazil.. '; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/flyweight-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { FlyweightComponent } from './flyweight/flyweight.component'; 5 | 6 | const routes: Routes = [{ path: '', component: FlyweightComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class FlyweightRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/flyweight.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { FlyweightRoutingModule } from './flyweight-routing.module'; 5 | import { FlyweightComponent } from './flyweight/flyweight.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | import {FormsModule} from '@angular/forms'; 8 | 9 | 10 | @NgModule({ 11 | declarations: [FlyweightComponent], 12 | imports: [ 13 | CommonModule, 14 | FlyweightRoutingModule, 15 | AngularMaterialModule, 16 | FormsModule 17 | ] 18 | }) 19 | export class FlyweightModule { } 20 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/flyweight/flyweight.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Flyweight Pattern (Cache) 4 |

5 |
6 | 7 | 8 | Select color & pen and draw your text 9 | 10 | 11 |
12 | 13 | Color 14 | 15 | red 16 | blue 17 | green 18 | black 19 | 20 | 21 |
22 |
23 | 24 | Thick pen 25 | Medium pen 26 | Thin pen 27 | 28 |
29 |
30 | 31 | Clearable input 32 | 33 | 36 | 37 |
38 |
39 | 40 |
41 |
42 | {{ log }} 43 |
44 |
45 |
46 |
47 |
48 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/flyweight/flyweight.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | 5 | div.container { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | } 10 | 11 | div.content { 12 | display: flex; 13 | flex-direction: row; 14 | align-items: flex-start; 15 | } 16 | 17 | 18 | mat-card { 19 | margin: 15px; 20 | max-width: 500px; 21 | } 22 | 23 | mat-button-toggle-group { 24 | margin-bottom: 20px; 25 | } 26 | 27 | button { 28 | margin-bottom: 15px; 29 | } 30 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/flyweight/flyweight.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {Pen} from '../models/pen.model'; 3 | import {PenFactory} from '../models/pen.factory'; 4 | import {Md5} from 'ts-md5'; 5 | 6 | @Component({ 7 | selector: 'app-flyweight', 8 | templateUrl: './flyweight.component.html', 9 | styleUrls: ['./flyweight.component.scss'] 10 | }) 11 | export class FlyweightComponent { 12 | 13 | // inspired by https://howtodoinjava.com/design-patterns/structural/flyweight-design-pattern/ 14 | 15 | public selectedPen: Pen; 16 | public selectedColor: string; 17 | public text: string; 18 | public listLog: string[]; 19 | 20 | constructor() { 21 | this.listLog = new Array(); 22 | } 23 | 24 | public selectThickPen(): void { 25 | this.selectedPen = PenFactory.getThickPen(this.selectedColor); 26 | } 27 | 28 | public selectThinPen(): void { 29 | this.selectedPen = PenFactory.getThinPen(this.selectedColor); 30 | } 31 | 32 | public selectMediumPen(): void { 33 | this.selectedPen = PenFactory.getMediumPen(this.selectedColor); 34 | } 35 | 36 | public selectColor(): void { 37 | this.selectedPen?.setColor(this.selectedColor); 38 | } 39 | 40 | public btnDraw(): void { 41 | const hashCode: string | Int32Array = Md5.hashStr(JSON.stringify(this.selectedPen)); 42 | this.listLog.push('Hash code of pen: ' + hashCode.toString()); 43 | this.listLog.push(this.selectedPen?.draw(this.text)); 44 | this.listLog.push(''); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/models/brush-size.enum.ts: -------------------------------------------------------------------------------- 1 | export enum BrushSize { 2 | THIN, 3 | MEDIUM, 4 | THICK 5 | } 6 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/models/pen.factory.ts: -------------------------------------------------------------------------------- 1 | import { MediumPen, Pen, ThickPen, ThinPen } from './pen.model'; 2 | 3 | interface IHash { 4 | [details: string]: Pen; 5 | } 6 | 7 | // Flyweight-Factory 8 | export class PenFactory { 9 | private static pensMap: IHash = {}; 10 | 11 | public static getThickPen(color: string): Pen { 12 | const key: string = color + '-THICK'; 13 | 14 | if (this.pensMap[key] != null) { 15 | return this.pensMap[key]; 16 | } else { 17 | const pen: Pen = new ThickPen(); 18 | pen.setColor(color); 19 | this.pensMap[key] = pen; 20 | return pen; 21 | } 22 | } 23 | 24 | public static getThinPen(color: string): Pen { 25 | const key: string = color + '-THIN'; 26 | 27 | if (this.pensMap[key] != null) { 28 | return this.pensMap[key]; 29 | } else { 30 | const pen: Pen = new ThinPen(); 31 | pen.setColor(color); 32 | this.pensMap[key] = pen; 33 | return pen; 34 | } 35 | } 36 | 37 | public static getMediumPen(color: string): Pen { 38 | const key: string = color + '-MEDIUM'; 39 | 40 | if (this.pensMap[key] != null) { 41 | return this.pensMap[key]; 42 | } else { 43 | const pen: Pen = new MediumPen(); 44 | pen.setColor(color); 45 | this.pensMap[key] = pen; 46 | return pen; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/app/11. Flyweight/models/pen.model.ts: -------------------------------------------------------------------------------- 1 | import { BrushSize } from './brush-size.enum'; 2 | 3 | // Flyweight 4 | export interface Pen { 5 | setColor(color: string): void; 6 | draw(content: string): string; 7 | } 8 | 9 | export class ThickPen implements Pen { 10 | private readonly brushSize = BrushSize.THICK; // intrinsic state - shareable 11 | private color: string; // extrinsic state - supplied by client 12 | 13 | public setColor(color: string): void { 14 | this.color = color; 15 | } 16 | 17 | public draw(content: string): string { 18 | return 'Draw THICK content "' + content + '" in color ' + this.color; 19 | } 20 | } 21 | 22 | export class ThinPen implements Pen { 23 | private readonly brushSize = BrushSize.THIN; // intrinsic state - shareable 24 | private color: string; // extrinsic state - supplied by client 25 | 26 | public setColor(color: string): void { 27 | this.color = color; 28 | } 29 | 30 | public draw(content: string): string { 31 | return 'Draw THIN content "' + content + '" in color ' + this.color; 32 | } 33 | } 34 | 35 | export class MediumPen implements Pen { 36 | private readonly brushSize = BrushSize.MEDIUM; // intrinsic state - shareable 37 | private color: string; // extrinsic state - supplied by client 38 | 39 | public setColor(color: string): void { 40 | this.color = color; 41 | } 42 | 43 | public draw(content: string): string { 44 | return 'Draw MEDIUM content "' + content + '" in color ' + this.color; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/app/12. Proxy/models/internet.model.ts: -------------------------------------------------------------------------------- 1 | export interface Internet { 2 | connect(): boolean; 3 | visitSite(site: string): boolean; 4 | } 5 | 6 | export class RealInternet implements Internet { 7 | private isConnected = false; 8 | 9 | public connect(): boolean { 10 | console.log('connect to the internet...'); 11 | this.isConnected = true; 12 | return true; 13 | } 14 | 15 | public visitSite(site: string): boolean { 16 | console.log('visit site:', site); 17 | return this.isConnected; 18 | } 19 | } 20 | 21 | export interface ProxyInternet extends Internet { 22 | authenticate(password: string): boolean; 23 | getBlacklistSites(): string[]; 24 | } 25 | 26 | export class Proxy implements ProxyInternet { 27 | readonly password: string = 'top-secret'; 28 | readonly blackList: string[] = ['www.123.com', 'www.abc.com', 'www.you-can-not-pass.com']; 29 | 30 | private internet: Internet; 31 | private isAuthenticated: boolean; 32 | 33 | constructor(internet: Internet) { 34 | this.internet = internet; 35 | this.isAuthenticated = false; 36 | } 37 | 38 | public authenticate(password: string): boolean { 39 | this.isAuthenticated = password === this.password; 40 | return this.isAuthenticated; 41 | } 42 | 43 | public connect(): boolean { 44 | console.log('Try to connect to the internet...'); 45 | if (!this.isAuthenticated) { 46 | return false; 47 | } 48 | return this.internet.connect(); 49 | } 50 | 51 | public visitSite(site: string): boolean { 52 | if (!this.isAuthenticated || !this.internet.visitSite(site)) { 53 | return this.internet.visitSite(site); 54 | } 55 | return this.blackList.indexOf(site) === -1; 56 | } 57 | 58 | public getBlacklistSites(): string[] { 59 | return this.blackList; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/app/12. Proxy/proxy-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { ProxyComponent } from './proxy/proxy.component'; 5 | 6 | const routes: Routes = [{ path: '', component: ProxyComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class ProxyRoutingModule {} 13 | -------------------------------------------------------------------------------- /src/app/12. Proxy/proxy.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { ProxyRoutingModule } from './proxy-routing.module'; 5 | import { ProxyComponent } from './proxy/proxy.component'; 6 | import { AngularMaterialModule } from '../modules/angular-material.module'; 7 | import {FormsModule} from '@angular/forms'; 8 | 9 | @NgModule({ 10 | declarations: [ProxyComponent], 11 | imports: [CommonModule, ProxyRoutingModule, AngularMaterialModule, FormsModule] 12 | }) 13 | export class ProxyModule {} 14 | -------------------------------------------------------------------------------- /src/app/12. Proxy/proxy/proxy.component.scss: -------------------------------------------------------------------------------- 1 | div { 2 | text-align: center; 3 | } 4 | 5 | div.container { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | } 10 | 11 | div.content { 12 | display: flex; 13 | flex-direction: row; 14 | align-items: flex-start; 15 | } 16 | 17 | mat-card { 18 | margin: 15px; 19 | max-width: 300px; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/12. Proxy/proxy/proxy.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { RealInternet, Proxy, Internet, ProxyInternet } from '../models/internet.model'; 3 | 4 | @Component({ 5 | selector: 'app-proxy', 6 | templateUrl: './proxy.component.html', 7 | styleUrls: ['./proxy.component.scss'] 8 | }) 9 | export class ProxyComponent { 10 | public logsInternet: string[]; 11 | public logsProxy: string[]; 12 | public selectedSite: string; 13 | public listSites: string[]; 14 | 15 | private internet: Internet; 16 | private proxy: ProxyInternet; 17 | private whiteList = ['www.mc-paper.com', 'www.abra.com', 'www.kadabra.com']; 18 | 19 | constructor() { 20 | this.logsInternet = new Array(); 21 | this.logsProxy = new Array(); 22 | this.init(); 23 | } 24 | 25 | private init() { 26 | this.internet = new RealInternet(); 27 | this.proxy = new Proxy(this.internet); 28 | this.listSites = [...this.proxy.getBlacklistSites(), ...this.whiteList]; 29 | } 30 | 31 | public btnConnectToRealInternet(): void { 32 | const success: boolean = this.internet.connect(); 33 | this.logsInternet.push('Connect to internet: ' + success.toString()); 34 | } 35 | 36 | public btnConnectToInternetWithProxy(): void { 37 | const success: boolean = this.proxy.connect(); 38 | this.logsProxy.push('Connect to internet: ' + success.toString()); 39 | } 40 | 41 | public selectionInternetChanged(): void { 42 | const success = this.internet.visitSite(this.selectedSite); 43 | this.logsInternet.push('visit "' + this.selectedSite + '" : ' + success.toString()); 44 | } 45 | 46 | public selectionProxyChanged(): void { 47 | const success = this.proxy.visitSite(this.selectedSite); 48 | this.logsProxy.push('visit "' + this.selectedSite + '" : ' + success.toString()); 49 | } 50 | 51 | public btnReset(): void { 52 | this.init(); 53 | } 54 | 55 | public btnAuthenticate(): void { 56 | const isAuthenticated: boolean = this.proxy.authenticate('top-secret'); 57 | this.logsProxy.push('Is authenticated: ' + isAuthenticated.toString()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/app/13. Mediator/mediator-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { MediatorComponent } from './mediator/mediator.component'; 5 | 6 | const routes: Routes = [{ path: '', component: MediatorComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class MediatorRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/13. Mediator/mediator.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { MediatorRoutingModule } from './mediator-routing.module'; 5 | import { MediatorComponent } from './mediator/mediator.component'; 6 | import { AngularMaterialModule } from '../modules/angular-material.module'; 7 | import { FormsModule } from '@angular/forms'; 8 | 9 | @NgModule({ 10 | declarations: [MediatorComponent], 11 | imports: [CommonModule, MediatorRoutingModule, AngularMaterialModule, FormsModule] 12 | }) 13 | export class MediatorModule {} 14 | -------------------------------------------------------------------------------- /src/app/13. Mediator/mediator/mediator.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Mediator Pattern (Intermediary, Controller) 4 |

5 |
6 |
7 | 8 | 9 | 10 | {{ user.name }} 11 | 12 | 13 | 14 |
15 | {{ msg }} 16 |
17 |
18 | 19 | 20 | Answer 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | 29 | 30 | 31 | Control 32 | 33 | 34 | 35 |
36 | 37 | Send to 38 | 39 | 40 | {{ user.name }} 41 | 42 | 43 | 44 | 45 | Message 46 | 47 | 48 | 49 |
50 |
51 |
52 |
53 |
54 |
55 | -------------------------------------------------------------------------------- /src/app/13. Mediator/mediator/mediator.component.scss: -------------------------------------------------------------------------------- 1 | div.column { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | } 6 | 7 | div.row { 8 | display: flex; 9 | flex-direction: row; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/13. Mediator/mediator/mediator.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Mediator } from '../models/mediator.interface'; 3 | import { ChatRoom } from '../models/chat-room.mediator'; 4 | import { ChatUser } from '../models/chat-user.model'; 5 | 6 | @Component({ 7 | selector: 'app-mediator', 8 | templateUrl: './mediator.component.html', 9 | styleUrls: ['./mediator.component.scss'] 10 | }) 11 | export class MediatorComponent { 12 | public sendToUser: ChatUser; 13 | public sendMessage: string; 14 | public answer: string; 15 | 16 | private readonly chatRoom: Mediator; 17 | 18 | private listUser: ChatUser[] = []; 19 | private admin: ChatUser; 20 | private user1: ChatUser; 21 | private user2: ChatUser; 22 | private user3: ChatUser; 23 | 24 | constructor() { 25 | this.answer = ''; 26 | this.chatRoom = new ChatRoom(); 27 | if (this.userFactory() === true) { 28 | this.addUserToChatRoom(); 29 | } 30 | } 31 | 32 | public get userList(): ChatUser[] { 33 | return this.listUser; 34 | } 35 | 36 | public btnSend(): void { 37 | this.admin.send(this.sendMessage, this.sendToUser.id); 38 | } 39 | 40 | public btnAnswer(userId: number): void { 41 | this.chatRoom.getUserByID(userId).send(this.answer, userId); 42 | } 43 | 44 | private userFactory(): boolean { 45 | try { 46 | this.admin = new ChatUser(this.chatRoom, 0, 'Morpheus'); 47 | this.user1 = new ChatUser(this.chatRoom, 1, 'John Doe'); 48 | this.user2 = new ChatUser(this.chatRoom, 2, 'Lucky Luke'); 49 | this.user3 = new ChatUser(this.chatRoom, 3, 'John Everyman'); 50 | this.listUser = [this.user1, this.user2, this.user3]; 51 | return true; 52 | } catch (e) { 53 | return false; 54 | } 55 | } 56 | 57 | private addUserToChatRoom() { 58 | this.listUser.forEach(user => { 59 | this.chatRoom.addUser(user); 60 | }); 61 | this.chatRoom.addUser(this.admin); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/app/13. Mediator/models/chat-room.mediator.ts: -------------------------------------------------------------------------------- 1 | import { Mediator } from './mediator.interface'; 2 | import { User } from './user.model'; 3 | 4 | interface IHash { 5 | [key: number]: User; 6 | } 7 | 8 | export class ChatRoom implements Mediator { 9 | private userMap: IHash = {}; 10 | 11 | public getUserNameByID(id: number): string { 12 | return this.userMap[id].name; 13 | } 14 | 15 | public getUserByID(id: number): User { 16 | return this.userMap[id]; 17 | } 18 | 19 | public notify(message: string, toUserId: number, fromUserId: number): void { 20 | if (this.userMap[toUserId] != null) { 21 | this.userMap[toUserId].receive(message, fromUserId); 22 | } 23 | } 24 | 25 | public addUser(user: User): void { 26 | this.userMap[user.id] = user; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/13. Mediator/models/chat-user.model.ts: -------------------------------------------------------------------------------- 1 | import { User } from './user.model'; 2 | import { Mediator } from './mediator.interface'; 3 | 4 | export class ChatUser extends User { 5 | private readonly listReceivedMessages: string[] = []; 6 | 7 | constructor(mediator: Mediator, userId: number, name: string) { 8 | super(mediator, userId, name); 9 | } 10 | 11 | public get receivedMessages(): string[] { 12 | return this.listReceivedMessages; 13 | } 14 | 15 | public send(message: string, toUserId: number): void { 16 | this.mediator.notify(message, toUserId, this.id); 17 | } 18 | 19 | public receive(message: string, fromUserId: number): void { 20 | this.listReceivedMessages.push(this.mediator.getUserNameByID(fromUserId) + ': ' + message); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/13. Mediator/models/mediator.interface.ts: -------------------------------------------------------------------------------- 1 | import { User } from './user.model'; 2 | 3 | export interface Mediator { 4 | notify(message: string, toUserId: number, fromUserId: number): void; 5 | addUser(user: User): void; 6 | getUserNameByID(id: number): string; 7 | getUserByID(id: number): User; 8 | } 9 | -------------------------------------------------------------------------------- /src/app/13. Mediator/models/user.model.ts: -------------------------------------------------------------------------------- 1 | import { Mediator } from './mediator.interface'; 2 | 3 | export abstract class User { 4 | private readonly _mediator: Mediator; 5 | private readonly _id: number; 6 | private readonly _name: string; 7 | 8 | protected constructor(mediator: Mediator, id: number, name: string) { 9 | this._mediator = mediator; 10 | this._name = name; 11 | this._id = id; 12 | } 13 | 14 | public abstract send(message: string, toUserId: number): void; 15 | public abstract receive(message: string, fromUserId: number): void; 16 | 17 | public get mediator(): Mediator { 18 | return this._mediator; 19 | } 20 | public get id(): number { 21 | return this._id; 22 | } 23 | public get name(): string { 24 | return this._name; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/14. Iterator/iterator-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { IteratorComponent } from './iterator/iterator.component'; 5 | 6 | const routes: Routes = [{ path: '', component: IteratorComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class IteratorRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/14. Iterator/iterator.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { IteratorRoutingModule } from './iterator-routing.module'; 5 | import { IteratorComponent } from './iterator/iterator.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | import {FormsModule} from '@angular/forms'; 8 | 9 | 10 | @NgModule({ 11 | declarations: [IteratorComponent], 12 | imports: [ 13 | CommonModule, 14 | IteratorRoutingModule, 15 | AngularMaterialModule, 16 | FormsModule 17 | ] 18 | }) 19 | export class IteratorModule { } 20 | -------------------------------------------------------------------------------- /src/app/14. Iterator/iterator/iterator.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Iterator Pattern 4 |

5 |
6 | 7 | 8 | 9 | Add item to collection 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | {{ output }} 20 |
21 |
22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /src/app/14. Iterator/iterator/iterator.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | margin-right: 20px; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/14. Iterator/iterator/iterator.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {WordsCollection} from '../models/words-collection.model'; 3 | import {Aggregator} from '../models/aggregator.interface'; 4 | import { Iterator } from '../models/iterator.interface'; 5 | 6 | @Component({ 7 | selector: 'app-iterator', 8 | templateUrl: './iterator.component.html', 9 | styleUrls: ['./iterator.component.scss'] 10 | }) 11 | export class IteratorComponent { 12 | 13 | public value: string; 14 | public output: string; 15 | 16 | readonly collection: Aggregator; 17 | readonly iterator: Iterator; 18 | 19 | constructor() { 20 | this.collection = new WordsCollection(); 21 | this.iterator = this.collection.getIterator(); 22 | this.value = ''; 23 | this.output = ''; 24 | } 25 | 26 | public btnAddItemToCollection(value: string) { 27 | this.collection.addItem(value); 28 | this.value = ''; 29 | document.getElementById('input').focus(); 30 | } 31 | 32 | public btnSliceCollectionItems(): void { 33 | this.output = ''; 34 | while (this.iterator.valid()) { 35 | this.output += this.iterator.next() + ','; 36 | } 37 | this.output = this.output.slice(0, -1); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/app/14. Iterator/models/aggregator.interface.ts: -------------------------------------------------------------------------------- 1 | import { Iterator } from './iterator.interface'; 2 | 3 | // Aggregate interface 4 | export interface Aggregator { 5 | getIterator(): Iterator; 6 | addItem(item: string): void; 7 | removeItem(item: string): void; 8 | } 9 | -------------------------------------------------------------------------------- /src/app/14. Iterator/models/iterator.interface.ts: -------------------------------------------------------------------------------- 1 | export interface Iterator { 2 | // Return the current element. 3 | current(): T; 4 | 5 | // Return the current element and move forward to next element. 6 | next(): T; 7 | 8 | // Return the key of the current element. 9 | key(): number; 10 | 11 | // Checks if current position is valid. 12 | valid(): boolean; 13 | 14 | // Rewind the Iterator to the first element. 15 | rewind(): void; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/14. Iterator/models/iterator.model.ts: -------------------------------------------------------------------------------- 1 | import { WordsCollection } from './words-collection.model'; 2 | import { Iterator } from './iterator.interface'; 3 | 4 | export class AlphabeticalOrderIterator implements Iterator { 5 | private collection: WordsCollection; 6 | private position: number; 7 | private readonly reverse: boolean = false; 8 | 9 | constructor(collection: WordsCollection, reverse: boolean = false) { 10 | this.collection = collection; 11 | this.reverse = reverse; 12 | this.position = 0; 13 | 14 | if (reverse === true) { 15 | this.position = collection.count - 1; 16 | } 17 | } 18 | 19 | public rewind(): void { 20 | this.position = this.reverse ? this.collection.count - 1 : 0; 21 | } 22 | 23 | public current(): string { 24 | return this.collection.items[this.position]; 25 | } 26 | 27 | public key(): number { 28 | return this.position; 29 | } 30 | 31 | public next(): string { 32 | const item: string = this.collection.items[this.position]; 33 | this.position += this.reverse ? -1 : 1; 34 | return item; 35 | } 36 | 37 | public valid(): boolean { 38 | if (this.reverse) { 39 | return this.position >= 0; 40 | } 41 | 42 | return this.position < this.collection.count; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/app/14. Iterator/models/words-collection.model.ts: -------------------------------------------------------------------------------- 1 | import { Iterator } from './iterator.interface'; 2 | import { Aggregator } from './aggregator.interface'; 3 | import { AlphabeticalOrderIterator } from './iterator.model'; 4 | 5 | // concrete Aggregate = collection 6 | export class WordsCollection implements Aggregator { 7 | private collectionItems: string[] = []; 8 | 9 | public get items(): string[] { 10 | return this.collectionItems; 11 | } 12 | 13 | public get count(): number { 14 | return this.collectionItems.length; 15 | } 16 | 17 | public addItem(item: string): void { 18 | this.collectionItems.push(item); 19 | } 20 | 21 | public removeItem(item: string): void { 22 | const index: number = this.collectionItems.indexOf(item); 23 | this.collectionItems.splice(index, 1); 24 | } 25 | 26 | // factory method 27 | public getIterator(): Iterator { 28 | return new AlphabeticalOrderIterator(this); 29 | } 30 | 31 | public getReverseIterator(): Iterator { 32 | return new AlphabeticalOrderIterator(this, true); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/15. Memento/memento-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { MementoComponent } from './memento/memento.component'; 5 | 6 | const routes: Routes = [{ path: '', component: MementoComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class MementoRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/15. Memento/memento.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { MementoRoutingModule } from './memento-routing.module'; 5 | import { MementoComponent } from './memento/memento.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | import {FormsModule} from '@angular/forms'; 8 | 9 | 10 | @NgModule({ 11 | declarations: [MementoComponent], 12 | imports: [ 13 | CommonModule, 14 | MementoRoutingModule, 15 | AngularMaterialModule, 16 | FormsModule 17 | ] 18 | }) 19 | export class MementoModule { } 20 | -------------------------------------------------------------------------------- /src/app/15. Memento/memento/memento.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Memento Pattern (Snapshot) 4 |

5 |
6 | 7 | 8 |
9 | 10 | Title 11 | 12 | 13 | 14 |
15 |
16 | 17 | Description 18 | 19 | 20 | 21 |
22 |
23 | 24 | Color 25 | 26 | 27 | 28 |
29 |
30 | 31 |
32 |
33 |

Backups until change:

34 |
35 |
36 |
{{ memento.getDate() }}
37 |
{{ memento.getState().title }}
38 |
{{ memento.getState().description }}
39 |
{{ memento.getState().color }}
40 |
41 |
42 |
43 |
44 |
45 | -------------------------------------------------------------------------------- /src/app/15. Memento/memento/memento.component.scss: -------------------------------------------------------------------------------- 1 | mat-card { 2 | max-width: 500px; 3 | } 4 | 5 | mat-card-content.mat-content { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: flex-start; 9 | } 10 | 11 | mat-form-field { 12 | margin-right: 20px; 13 | } 14 | 15 | div.title-backups { 16 | margin-top: 15px; 17 | } 18 | 19 | button { 20 | width: 155px; 21 | } 22 | -------------------------------------------------------------------------------- /src/app/15. Memento/memento/memento.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ConcreteOrginator, Orginator } from '../models/orginator.model'; 3 | import { CareTaker, ConcreteCareTaker } from '../models/care-taker.model'; 4 | import { Card, MatCard } from '../models/card.model'; 5 | import {Memento} from '../models/memento.model'; 6 | 7 | @Component({ 8 | selector: 'app-memento', 9 | templateUrl: './memento.component.html', 10 | styleUrls: ['./memento.component.scss'] 11 | }) 12 | export class MementoComponent { 13 | public history: Memento[]; 14 | public title = ''; 15 | public description = ''; 16 | public color = ''; 17 | 18 | private readonly orginator: Orginator; 19 | private readonly careTaker: CareTaker; 20 | private readonly currentCardState: Card; 21 | 22 | constructor() { 23 | this.history = new Array(); 24 | this.currentCardState = new MatCard('Default title', 'Default description', 'white'); 25 | this.orginator = new ConcreteOrginator(this.currentCardState); 26 | this.careTaker = new ConcreteCareTaker(this.orginator); 27 | this.history = this.careTaker.history(); 28 | } 29 | 30 | public btnChangeTitle(title: string): void { 31 | this.careTaker.backUp(); 32 | this.orginator.changeTitle(title); 33 | } 34 | 35 | public btnChangeDescription(description: string): void { 36 | this.careTaker.backUp(); 37 | this.orginator.changeDescription(description); 38 | } 39 | 40 | public btnChangeColor(color: string): void { 41 | this.careTaker.backUp(); 42 | this.orginator.changeColor(color); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/app/15. Memento/models/card.model.ts: -------------------------------------------------------------------------------- 1 | export interface Card { 2 | title: string; 3 | description: string; 4 | color: string; 5 | } 6 | 7 | export class MatCard implements Card { 8 | public title: string; 9 | public description: string; 10 | public color: string; 11 | 12 | constructor(title: string, description: string, color: string) { 13 | this.title = title; 14 | this.description = description; 15 | this.color = color; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/15. Memento/models/care-taker.model.ts: -------------------------------------------------------------------------------- 1 | import {Memento} from './memento.model'; 2 | import {Orginator} from './orginator.model'; 3 | 4 | export interface CareTaker { 5 | backUp(): void; 6 | undo(): void; 7 | history(): Memento[]; 8 | } 9 | 10 | export class ConcreteCareTaker implements CareTaker { 11 | private listMemento: Memento[] = []; 12 | private orginator: Orginator; 13 | 14 | constructor(orginator: Orginator) { 15 | this.orginator = orginator; 16 | } 17 | 18 | public backUp(): void { 19 | this.listMemento.push(this.orginator.saveState()); 20 | } 21 | 22 | public undo(): void { 23 | if (!this.listMemento.length) { 24 | return; 25 | } 26 | 27 | const memento: Memento = this.listMemento.pop(); 28 | this.orginator.restoreState(memento); 29 | } 30 | 31 | public history(): Memento[] { 32 | console.log(this.listMemento); 33 | return this.listMemento; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/15. Memento/models/memento.model.ts: -------------------------------------------------------------------------------- 1 | import { Card } from './card.model'; 2 | 3 | export interface Memento { 4 | getState(): Card; 5 | getDate(): string; 6 | } 7 | 8 | export class ConcreteMemento implements Memento { 9 | private readonly state: Card; 10 | private readonly date: string; 11 | 12 | constructor(state: Card) { 13 | this.state = state; 14 | this.date = new Date(Date.now()).toString(); 15 | } 16 | 17 | /* restoring the state */ 18 | public getState(): Card { 19 | return this.state; 20 | } 21 | 22 | public getDate(): string { 23 | return this.date; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/15. Memento/models/orginator.model.ts: -------------------------------------------------------------------------------- 1 | import {Card, MatCard} from './card.model'; 2 | import { ConcreteMemento, Memento } from './memento.model'; 3 | 4 | export interface Orginator { 5 | changeTitle(value: string): void; 6 | changeDescription(value: string): void; 7 | changeColor(value: string): void; 8 | saveState(): Memento; 9 | restoreState(memento: Memento): void; 10 | } 11 | 12 | /* responsibility for state handling */ 13 | export class ConcreteOrginator implements Orginator { 14 | private currentState: Card; 15 | 16 | constructor(state: Card) { 17 | this.currentState = state; 18 | } 19 | 20 | public changeTitle(value: string): void { 21 | this.currentState.title = value; 22 | } 23 | 24 | public changeDescription(value: string): void { 25 | this.currentState.description = value; 26 | } 27 | 28 | public changeColor(value: string): void { 29 | this.currentState.color = value; 30 | } 31 | 32 | /** create memento **/ 33 | public saveState(): Memento { 34 | return new ConcreteMemento(new MatCard(this.currentState.title, this.currentState.description, this.currentState.color)); 35 | } 36 | 37 | /** set memento **/ 38 | public restoreState(memento: Memento): void { 39 | this.currentState = memento.getState(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/16. Strategy/models/algorithm.model.ts: -------------------------------------------------------------------------------- 1 | import { Strategy } from './strategy.model'; 2 | 3 | export class Algorithm { 4 | private _strategy: Strategy; 5 | private arr: number[] = [54, 2, 89, 12, 24, 68, 34, 77, 31, 40, 92]; 6 | 7 | constructor(strategy: Strategy) { 8 | this._strategy = strategy; 9 | } 10 | 11 | public set strategy(strategy: Strategy) { 12 | this._strategy = strategy; 13 | } 14 | 15 | public get array(): string { 16 | return this.arr.join(','); 17 | } 18 | 19 | public sort(): string { 20 | const result: number[] = this._strategy.sort([...this.arr]); 21 | return result.join(','); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/app/16. Strategy/strategy-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { StrategyComponent } from './strategy/strategy.component'; 5 | 6 | const routes: Routes = [{ path: '', component: StrategyComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class StrategyRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/16. Strategy/strategy.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { StrategyRoutingModule } from './strategy-routing.module'; 5 | import { StrategyComponent } from './strategy/strategy.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | import {FormsModule} from '@angular/forms'; 8 | 9 | 10 | @NgModule({ 11 | declarations: [StrategyComponent], 12 | imports: [ 13 | CommonModule, 14 | StrategyRoutingModule, 15 | AngularMaterialModule, 16 | FormsModule 17 | ] 18 | }) 19 | export class StrategyModule { } 20 | -------------------------------------------------------------------------------- /src/app/16. Strategy/strategy/strategy.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Strategy Pattern 4 |

5 |
6 | 7 | 8 |

{{array}}

9 | 10 | 11 | {{ algo.name }} 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | {{result}} 20 | 21 |
22 |
23 |
24 | -------------------------------------------------------------------------------- /src/app/16. Strategy/strategy/strategy.component.scss: -------------------------------------------------------------------------------- 1 | .mat-radio-button ~ .mat-radio-button { 2 | margin-left: 16px; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/16. Strategy/strategy/strategy.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import {MergeSort, QuickSort, Strategy} from '../models/strategy.model'; 3 | import {Algorithm} from '../models/algorithm.model'; 4 | 5 | @Component({ 6 | selector: 'app-strategy', 7 | templateUrl: './strategy.component.html', 8 | styleUrls: ['./strategy.component.scss'] 9 | }) 10 | export class StrategyComponent { 11 | 12 | private algorithm: Algorithm; 13 | public listAlgorithm: Strategy[]; 14 | public selectedAlgorithm: Strategy; 15 | public result = ''; 16 | 17 | constructor() { 18 | // using factory method would be better 19 | this.listAlgorithm = [ new MergeSort(), new QuickSort()]; 20 | this.selectedAlgorithm = this.listAlgorithm[0]; 21 | this.algorithm = new Algorithm(this.selectedAlgorithm); 22 | } 23 | 24 | public btnSort(): void { 25 | this.algorithm.strategy = this.selectedAlgorithm; 26 | this.result = this.algorithm.sort(); 27 | } 28 | 29 | public get array(): string { 30 | return this.algorithm.array ? this.algorithm.array : ''; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/17. Command/command-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { CommandComponent } from './command/command.component'; 5 | 6 | const routes: Routes = [{ path: '', component: CommandComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class CommandRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/17. Command/command.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { CommandRoutingModule } from './command-routing.module'; 5 | import { CommandComponent } from './command/command.component'; 6 | import { AngularMaterialModule } from '../modules/angular-material.module'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [CommandComponent], 11 | imports: [ 12 | CommonModule, 13 | CommandRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class CommandModule { } 18 | -------------------------------------------------------------------------------- /src/app/17. Command/command/command.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Command Pattern (Action, Transaction) 4 |

5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Current editor state 16 | 17 | 18 | 19 |
20 | {{ log }} 21 |
22 |
23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /src/app/17. Command/command/command.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/src/app/17. Command/command/command.component.scss -------------------------------------------------------------------------------- /src/app/17. Command/command/command.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CommandComponent } from './command.component'; 4 | import { AngularMaterialModule } from '../../modules/angular-material.module'; 5 | 6 | describe('CommandComponent', () => { 7 | let component: CommandComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async () => { 11 | await TestBed.configureTestingModule({ 12 | declarations: [CommandComponent], 13 | imports: [AngularMaterialModule] 14 | }).compileComponents(); 15 | }); 16 | 17 | beforeEach(() => { 18 | fixture = TestBed.createComponent(CommandComponent); 19 | component = fixture.componentInstance; 20 | fixture.detectChanges(); 21 | }); 22 | 23 | it('should create', () => { 24 | expect(component).toBeTruthy(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /src/app/17. Command/command/command.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Editor, TextEditor } from '../models/editor.model'; 3 | import { EditorInvoker } from '../models/editor.invoker'; 4 | import { EditorClose, EditorEdit, EditorOpen, EditorSave } from '../models/editor.command'; 5 | 6 | @Component({ 7 | selector: 'app-command', 8 | templateUrl: './command.component.html', 9 | styleUrls: ['./command.component.scss'] 10 | }) 11 | export class CommandComponent { 12 | 13 | public listLog: string[] = []; 14 | 15 | private readonly editor: Editor; 16 | private editorInvoker: EditorInvoker; 17 | 18 | constructor() { 19 | this.editor = new TextEditor(); 20 | this.editorInvoker = new EditorInvoker( 21 | new EditorOpen(this.editor), 22 | new EditorClose(this.editor), 23 | new EditorEdit(this.editor), 24 | new EditorSave(this.editor) 25 | ); 26 | } 27 | 28 | public btnOpen(): void { 29 | this.listLog.push(this.editorInvoker.pressOpen()); 30 | } 31 | 32 | public btnClose(): void { 33 | this.listLog.push(this.editorInvoker.pressClose()); 34 | } 35 | 36 | public btnEdit(): void { 37 | this.listLog.push(this.editorInvoker.pressEdit()); 38 | } 39 | 40 | public btnSave(): void { 41 | this.listLog.push(this.editorInvoker.pressSave()); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/app/17. Command/models/command.interface.ts: -------------------------------------------------------------------------------- 1 | export interface Command { 2 | execute(): string; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/17. Command/models/editor.command.ts: -------------------------------------------------------------------------------- 1 | import { Command } from './command.interface'; 2 | import { Editor } from './editor.model'; 3 | 4 | export class EditorOpen implements Command { 5 | private editor: Editor; 6 | 7 | constructor(editor: Editor) { 8 | this.editor = editor; 9 | } 10 | 11 | public execute(): string { 12 | return this.editor.open(); 13 | } 14 | } 15 | 16 | export class EditorEdit implements Command { 17 | private editor: Editor; 18 | 19 | constructor(editor: Editor) { 20 | this.editor = editor; 21 | } 22 | 23 | public execute(): string { 24 | return this.editor.edit(); 25 | } 26 | } 27 | 28 | export class EditorSave implements Command { 29 | private editor: Editor; 30 | 31 | constructor(editor: Editor) { 32 | this.editor = editor; 33 | } 34 | 35 | public execute(): string { 36 | return this.editor.save(); 37 | } 38 | } 39 | 40 | export class EditorClose implements Command { 41 | private editor: Editor; 42 | 43 | constructor(editor: Editor) { 44 | this.editor = editor; 45 | } 46 | 47 | public execute(): string { 48 | return this.editor.close(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/app/17. Command/models/editor.invoker.ts: -------------------------------------------------------------------------------- 1 | import { Command } from './command.interface'; 2 | 3 | export class EditorInvoker { 4 | private onOpen: Command; 5 | private onClose: Command; 6 | private onEdit: Command; 7 | private onSave: Command; 8 | 9 | constructor(open: Command, close: Command, edit: Command, save: Command) { 10 | this.onOpen = open; 11 | this.onClose = close; 12 | this.onEdit = edit; 13 | this.onSave = save; 14 | } 15 | 16 | public setOnOpen(command: Command): void { 17 | this.onOpen = command; 18 | } 19 | 20 | public setOnClose(command: Command): void { 21 | this.onClose = command; 22 | } 23 | 24 | public setOnEdit(command: Command): void { 25 | this.onEdit = command; 26 | } 27 | 28 | public setOnSave(command: Command): void { 29 | this.onSave = command; 30 | } 31 | 32 | public pressOpen(): string { 33 | return this.onOpen.execute(); 34 | } 35 | 36 | public pressClose(): string { 37 | return this.onClose.execute(); 38 | } 39 | 40 | public pressEdit(): string { 41 | return this.onEdit.execute(); 42 | } 43 | 44 | public pressSave(): string { 45 | return this.onSave.execute(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/app/17. Command/models/editor.model.ts: -------------------------------------------------------------------------------- 1 | // Receiver interface 2 | export interface Editor { 3 | open(): string; 4 | edit(): string; 5 | save(): string; 6 | close(): string; 7 | } 8 | 9 | // Receiver 10 | export class TextEditor implements Editor { 11 | public open(): string { 12 | return 'Text-Editor is opened'; 13 | } 14 | public edit(): string { 15 | return 'Text-Editor is edited'; 16 | } 17 | public save(): string { 18 | return 'Text-Editor is saved'; 19 | } 20 | public close(): string { 21 | return 'Text-Editor is closed'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/app/18. Observer/models/channel-clients.model.ts: -------------------------------------------------------------------------------- 1 | import {Observer, Subject} from './interfaces'; 2 | import {ChannelServer} from './channel-server.model'; 3 | 4 | export class ChannelA implements Observer { 5 | private readonly listMessages: string[]; 6 | 7 | constructor() { 8 | this.listMessages = []; 9 | } 10 | 11 | public get messages(): string[] { 12 | return [...this.listMessages]; 13 | } 14 | public update(subject: Subject): void { 15 | if (!(subject instanceof ChannelServer)) { 16 | this.listMessages.push('Invalid sender.'); 17 | return; 18 | } 19 | if (subject.state < 3) { 20 | this.listMessages.push('(Received number < 3) => ' + subject.state); 21 | } else { 22 | this.listMessages.push('...'); 23 | } 24 | } 25 | } 26 | 27 | export class ChannelB implements Observer { 28 | private readonly listMessages: string[]; 29 | 30 | constructor() { 31 | this.listMessages = []; 32 | } 33 | 34 | public get messages(): string[] { 35 | return [...this.listMessages]; 36 | } 37 | 38 | public update(subject: Subject): void { 39 | if (!(subject instanceof ChannelServer)) { 40 | this.listMessages.push('Invalid sender.'); 41 | return; 42 | } 43 | if (subject.state > 2) { 44 | this.listMessages.push('(Received number > 2) => ' + subject.state); 45 | } else { 46 | this.listMessages.push('...'); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/app/18. Observer/models/channel-server.model.ts: -------------------------------------------------------------------------------- 1 | import { Observer, Subject } from './interfaces'; 2 | 3 | // concrete subject 4 | export class ChannelServer implements Subject { 5 | public state: number; 6 | private observers: Observer[] = []; 7 | 8 | public attach(observer: Observer): void { 9 | if (this.observers.includes(observer)) { 10 | console.log('Subject: Observer has been attached already.'); 11 | } else { 12 | this.observers.push(observer); 13 | } 14 | } 15 | 16 | public detach(observer: Observer): void { 17 | const observerIndex = this.observers.indexOf(observer); 18 | if (observerIndex === -1) { 19 | return console.log('Subject: Nonexistent observer.'); 20 | } 21 | 22 | this.observers.splice(observerIndex, 1); 23 | } 24 | 25 | public notify(): void { 26 | for (const observer of this.observers) { 27 | observer.update(this); 28 | } 29 | } 30 | 31 | public calculateRandomNumber(): void { 32 | this.state = Math.floor(Math.random() * (10 + 1)); 33 | this.notify(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/18. Observer/models/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface Observer { 2 | messages: string[]; 3 | update(subject: Subject): void; 4 | } 5 | 6 | export interface Subject { 7 | attach(observer: Observer): void; 8 | detach(observer: Observer): void; 9 | notify(): void; 10 | calculateRandomNumber(): void; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/18. Observer/observer-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { ObserverComponent } from './observer/observer.component'; 5 | 6 | const routes: Routes = [{ path: '', component: ObserverComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class ObserverRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/18. Observer/observer.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { ObserverRoutingModule } from './observer-routing.module'; 5 | import { ObserverComponent } from './observer/observer.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [ObserverComponent], 11 | imports: [ 12 | CommonModule, 13 | ObserverRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class ObserverModule { } 18 | -------------------------------------------------------------------------------- /src/app/18. Observer/observer/observer.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Observer Pattern 4 |

5 |

(Event-Subscriber, Listener)

6 |
7 | 8 | 9 | 10 | 11 | 12 |
13 |

Channel A

14 |
15 | {{ message }} 16 |
17 |
18 |
19 |

Channel B

20 |
21 | {{ message }} 22 |
23 |
24 |
25 | 26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /src/app/18. Observer/observer/observer.component.scss: -------------------------------------------------------------------------------- 1 | mat-card { 2 | width: 400px; 3 | max-width: 400px; 4 | } 5 | 6 | mat-card-content { 7 | display: flex; 8 | flex-direction: row; 9 | justify-content: space-around; 10 | 11 | div { 12 | width: 180px; 13 | border: solid 1px grey; 14 | 15 | div { 16 | border: 0; 17 | } 18 | } 19 | 20 | div:first-of-type { 21 | margin-right: 15px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/app/18. Observer/observer/observer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Observer, Subject } from '../models/interfaces'; 3 | import { ChannelA, ChannelB } from '../models/channel-clients.model'; 4 | import { ChannelServer } from '../models/channel-server.model'; 5 | 6 | @Component({ 7 | selector: 'app-observer', 8 | templateUrl: './observer.component.html', 9 | styleUrls: ['./observer.component.scss'] 10 | }) 11 | export class ObserverComponent { 12 | 13 | public get messageChannelA(): string[] { 14 | return this.channelA.messages; 15 | } 16 | 17 | public get messageChannelB(): string[] { 18 | return this.channelB.messages; 19 | } 20 | 21 | private chatServer: Subject; 22 | private readonly channelA: Observer; 23 | private readonly channelB: Observer; 24 | 25 | constructor() { 26 | this.chatServer = new ChannelServer(); 27 | this.channelA = new ChannelA(); 28 | this.chatServer.attach(this.channelA); 29 | this.channelB = new ChannelB(); 30 | this.chatServer.attach(this.channelB); 31 | } 32 | 33 | public btnGenerateRandomNumber(): void { 34 | this.chatServer.calculateRandomNumber(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/app/19. Visitor/models/fruit.factory.ts: -------------------------------------------------------------------------------- 1 | import { Apple, Banana, Cherry, Orange } from './fruit.model'; 2 | import { Fruit } from './fruit.interface'; 3 | import { Size } from './size.enum'; 4 | 5 | export class FruitFactory { 6 | public getFruits(): Fruit[] { 7 | const result: Fruit[] = []; 8 | result.push(new Orange(0, 'Mandarin', 'red', Size.S)); 9 | result.push(new Apple(0, 'Gala', 'red', Size.S)); 10 | result.push(new Cherry(0, 'Rainier', 'red', Size.S)); 11 | result.push(new Apple(0, 'Gala', 'red', Size.XL)); 12 | result.push(new Apple(0, 'Honeycrisp', 'orange', Size.XL)); 13 | result.push(new Orange(0, 'Tangerine', 'orange', Size.S)); 14 | result.push(new Orange(0, 'Mandarin', 'red', Size.L)); 15 | result.push(new Banana(0, 'Lady Finger Banana', 'yellow', Size.L)); 16 | result.push(new Orange(0, 'Mandarin', 'red', Size.S)); 17 | result.push(new Banana(0, 'Lady Finger Banana', 'yellow', Size.XL)); 18 | result.push(new Cherry(0, 'Rainier', 'red', Size.S)); 19 | result.push(new Orange(0, 'Tangerine', 'red', Size.S)); 20 | result.push(new Apple(0, 'Gala', 'orange', Size.M)); 21 | result.push(new Cherry(0, 'Morello', 'depp red', Size.S)); 22 | result.push(new Apple(0, 'Honeycrisp', 'orange', Size.L)); 23 | return result; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/19. Visitor/models/fruit.interface.ts: -------------------------------------------------------------------------------- 1 | import { FruitVisitor } from './fruit.visitor'; 2 | import { Size } from './size.enum'; 3 | 4 | export interface Fruit { 5 | id: number; 6 | name: string; 7 | type: string; 8 | color: string; 9 | size: Size; 10 | accept(visitor: FruitVisitor): void; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/19. Visitor/models/fruit.visitor.ts: -------------------------------------------------------------------------------- 1 | import { Fruit } from './fruit.interface'; 2 | 3 | // Visitor 4 | export interface FruitVisitor { 5 | oranges: Fruit[]; 6 | apples: Fruit[]; 7 | bananas: Fruit[]; 8 | cherries: Fruit[]; 9 | visitOrange(fruit: Fruit): void; 10 | visitApple(fruit: Fruit): void; 11 | visitBanana(fruit: Fruit): void; 12 | visitCherry(fruit: Fruit): void; 13 | } 14 | 15 | // Concrete visitor 16 | export class FruitPartitioner implements FruitVisitor { 17 | private listOrange: Fruit[] = []; 18 | private listApple: Fruit[] = []; 19 | private listBanana: Fruit[] = []; 20 | private listCherry: Fruit[] = []; 21 | 22 | public visitOrange(fruit: Fruit): void { 23 | this.listOrange.push(fruit); 24 | } 25 | 26 | public visitApple(fruit: Fruit): void { 27 | this.listApple.push(fruit); 28 | } 29 | 30 | public visitBanana(fruit: Fruit): void { 31 | this.listBanana.push(fruit); 32 | } 33 | 34 | public visitCherry(fruit: Fruit): void { 35 | this.listCherry.push(fruit); 36 | } 37 | 38 | public get oranges(): Fruit[] { 39 | return this.listOrange; 40 | } 41 | 42 | public get apples(): Fruit[] { 43 | return this.listApple; 44 | } 45 | 46 | public get bananas(): Fruit[] { 47 | return this.listBanana; 48 | } 49 | 50 | public get cherries(): Fruit[] { 51 | return this.listCherry; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/app/19. Visitor/models/size.enum.ts: -------------------------------------------------------------------------------- 1 | export enum Size { 2 | S, 3 | M, 4 | L, 5 | XL, 6 | XXL, 7 | XXXL, 8 | XXXXL 9 | } 10 | -------------------------------------------------------------------------------- /src/app/19. Visitor/visitor-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { VisitorComponent } from './visitor/visitor.component'; 5 | 6 | const routes: Routes = [{ path: '', component: VisitorComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class VisitorRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/19. Visitor/visitor.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { VisitorRoutingModule } from './visitor-routing.module'; 5 | import { VisitorComponent } from './visitor/visitor.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [VisitorComponent], 11 | imports: [ 12 | CommonModule, 13 | VisitorRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class VisitorModule { } 18 | -------------------------------------------------------------------------------- /src/app/19. Visitor/visitor/visitor.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Visitor Pattern 4 |

5 |
6 | 7 | 8 | Fruits 9 | 10 | 11 |
12 | 13 |
id: {{ fruit.id }}
14 |
name: {{ fruit.name }}
15 |
color: {{ fruit.color }}
16 |
size: {{ getSize(fruit.size) }}
17 |
type: {{ fruit.type }}
18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 |
26 | {{msg}} 27 |
28 |
29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /src/app/19. Visitor/visitor/visitor.component.scss: -------------------------------------------------------------------------------- 1 | mat-card { 2 | width: 570px; 3 | max-width: 570px; 4 | } 5 | 6 | mat-card.fruit { 7 | width: 80px; 8 | max-width: 80px; 9 | } 10 | 11 | mat-card.fruit { 12 | width: 80px; 13 | max-width: 80px; 14 | } 15 | 16 | div.fruits { 17 | display: flex; 18 | flex-direction: row; 19 | flex-wrap: wrap; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/19. Visitor/visitor/visitor.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Fruit } from '../models/fruit.interface'; 3 | import { FruitFactory } from '../models/fruit.factory'; 4 | import { FruitPartitioner, FruitVisitor } from '../models/fruit.visitor'; 5 | import { Size } from '../models/size.enum'; 6 | 7 | @Component({ 8 | selector: 'app-visitor', 9 | templateUrl: './visitor.component.html', 10 | styleUrls: ['./visitor.component.scss'] 11 | }) 12 | export class VisitorComponent { 13 | // https://stackoverflow.com/questions/2604169/visitor-patterns-purpose-with-examples 14 | 15 | public size = Size; 16 | 17 | private readonly fruitPartitioner: FruitVisitor; 18 | private readonly _listFruit: Fruit[]; 19 | 20 | public get listFruit(): Fruit[] { 21 | return this._listFruit; 22 | } 23 | 24 | public log: string[] = []; 25 | 26 | constructor() { 27 | this._listFruit = new FruitFactory().getFruits(); 28 | this.fruitPartitioner = new FruitPartitioner(); 29 | } 30 | 31 | public getSize(sizeAsNumber: number): string { 32 | return this.size[sizeAsNumber]; 33 | } 34 | 35 | btnPartition(): void { 36 | console.log(this.listFruit); 37 | // best practise: iterator pattern for foreach-loops 38 | this.listFruit.forEach((fruit: Fruit) => { 39 | // calls the accept method of the concrete object, e.g. Orange.accept 40 | // in this example, orange's accept method is called 5 times > so, length = 5 41 | fruit.accept(this.fruitPartitioner); 42 | }); 43 | 44 | this.log.push('Oranges: ' + this.fruitPartitioner.oranges.length.toString()); 45 | this.log.push('Apples: ' + this.fruitPartitioner.apples.length.toString()); 46 | this.log.push('Bananas: ' + this.fruitPartitioner.bananas.length.toString()); 47 | this.log.push('Cherries: ' + this.fruitPartitioner.cherries.length.toString()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/app/20. State/models/phone.context.ts: -------------------------------------------------------------------------------- 1 | import { MobilePhoneOptions } from './phone.options'; 2 | import { LockedScreen, MobilePhoneState } from './screen.state'; 3 | 4 | // Context 5 | export class MobilePhone implements MobilePhoneOptions { 6 | private _state: MobilePhoneState; 7 | private countLockedScreen: number; 8 | 9 | constructor() { 10 | this.countLockedScreen = 0; 11 | this._state = new LockedScreen(); 12 | this.logCurrentState(); 13 | } 14 | 15 | private logCurrentState(): void { 16 | console.log(this._state); 17 | } 18 | 19 | public get state(): MobilePhoneState { 20 | return this._state; 21 | } 22 | 23 | public get name(): string { 24 | return this._state.name; 25 | } 26 | 27 | public lockScreen(): void { 28 | this.countLockedScreen >= 5 29 | ? (this._state = this._state.showLowBatteryScreen()) 30 | : (this._state = this._state.lockScreen()); 31 | ++this.countLockedScreen; 32 | this.logCurrentState(); 33 | } 34 | public unlockScreen(): void { 35 | this._state = this._state.unlockScreen(); 36 | this.logCurrentState(); 37 | } 38 | public showLowBatteryScreen(): void { 39 | this._state = this._state.showLowBatteryScreen(); 40 | this.logCurrentState(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/app/20. State/models/phone.options.ts: -------------------------------------------------------------------------------- 1 | import { MobilePhoneState } from './screen.state'; 2 | 3 | export interface MobilePhoneOptions { 4 | state: MobilePhoneState; 5 | name: string; 6 | lockScreen(): void; 7 | unlockScreen(): void; 8 | showLowBatteryScreen(): void; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/20. State/models/screen.state.ts: -------------------------------------------------------------------------------- 1 | import { MobilePhoneOptions } from './phone.options'; 2 | 3 | // State 4 | export abstract class MobilePhoneState implements MobilePhoneOptions { 5 | public get name(): string { 6 | throw new Error('Invalid operation'); 7 | } 8 | public get state(): MobilePhoneState { 9 | throw new Error('Invalid operation'); 10 | } 11 | public lockScreen(): MobilePhoneState { 12 | throw new Error('Invalid operation'); 13 | } 14 | public unlockScreen(): MobilePhoneState { 15 | throw new Error('Invalid operation'); 16 | } 17 | public showLowBatteryScreen(): MobilePhoneState { 18 | throw new Error('Invalid operation'); 19 | } 20 | } 21 | 22 | export class LockedScreen extends MobilePhoneState { 23 | public get name(): string { 24 | return 'LockedScreen'; 25 | } 26 | 27 | public unlockScreen(): MobilePhoneState { 28 | return new UnLockedScreen(); 29 | } 30 | } 31 | 32 | export class UnLockedScreen extends MobilePhoneState { 33 | public get name(): string { 34 | return 'UnLockedScreen'; 35 | } 36 | 37 | public lockScreen(): MobilePhoneState { 38 | return new LockedScreen(); 39 | } 40 | 41 | public showLowBatteryScreen(): MobilePhoneState { 42 | return new LowBatteryScreen(); 43 | } 44 | } 45 | 46 | export class LowBatteryScreen extends MobilePhoneState { 47 | public get name(): string { 48 | return 'LowBatteryScreen'; 49 | } 50 | 51 | public unlockScreen(): MobilePhoneState { 52 | return new UnLockedScreen(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/20. State/state-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { StateComponent } from './state/state.component'; 5 | 6 | const routes: Routes = [{ path: '', component: StateComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class StateRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/20. State/state.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { StateRoutingModule } from './state-routing.module'; 5 | import { StateComponent } from './state/state.component'; 6 | import { AngularMaterialModule } from '../modules/angular-material.module'; 7 | 8 | @NgModule({ 9 | declarations: [StateComponent], 10 | imports: [ 11 | CommonModule, 12 | StateRoutingModule, 13 | AngularMaterialModule 14 | ] 15 | }) 16 | export class StateModule { } 17 | -------------------------------------------------------------------------------- /src/app/20. State/state/state.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | State Pattern 4 |

5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Current screen state 14 | 15 | 16 | If you lock the screen to often, the battery get low 17 | 18 | 19 | 20 | {{ state.name }} 21 | 22 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /src/app/20. State/state/state.component.scss: -------------------------------------------------------------------------------- 1 | mat-card { 2 | width: 400px; 3 | max-width: 400px; 4 | } 5 | 6 | mat-card-header.mat-card-header { 7 | justify-content: center; 8 | } 9 | -------------------------------------------------------------------------------- /src/app/20. State/state/state.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { MobilePhoneOptions } from '../models/phone.options'; 3 | import { MobilePhone } from '../models/phone.context'; 4 | import { MobilePhoneState } from '../models/screen.state'; 5 | 6 | @Component({ 7 | selector: 'app-state', 8 | templateUrl: './state.component.html', 9 | styleUrls: ['./state.component.scss'] 10 | }) 11 | export class StateComponent { 12 | // inspired by https://dev.to/lifelongthinker/the-state-pattern-exemplified-4cbe 13 | 14 | public mobilePhone: MobilePhoneOptions; 15 | public state: MobilePhoneState; 16 | 17 | constructor() { 18 | this.mobilePhone = new MobilePhone(); 19 | this.state = this.mobilePhone.state; 20 | } 21 | 22 | public btnLockScreen(): void { 23 | this.mobilePhone.lockScreen(); 24 | this.state = this.mobilePhone.state; 25 | } 26 | 27 | public btnUnlockScreen(): void { 28 | this.mobilePhone.unlockScreen(); 29 | this.state = this.mobilePhone.state; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/21. Template Method/models/online.order.ts: -------------------------------------------------------------------------------- 1 | import { OrderTemplate } from './order.template'; 2 | 3 | export class OnlineOrder extends OrderTemplate { 4 | public selectProducts(): string { 5 | const result: string[] = []; 6 | result.push('Item added to online shopping cart'); 7 | result.push('Get gift wrap preference'); 8 | result.push('Get delivery address.'); 9 | return result.join(','); 10 | } 11 | public payProducts(): string { 12 | return 'Online payment through Netbanking, card or immediate reimbursement.'; 13 | } 14 | 15 | public deliverProducts(): string { 16 | return 'Ship the item through post to delivery address'; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/app/21. Template Method/models/order.template.ts: -------------------------------------------------------------------------------- 1 | export abstract class OrderTemplate { 2 | private _isGift: boolean; 3 | 4 | public abstract selectProducts(): string; 5 | public abstract payProducts(): string; 6 | public abstract deliverProducts(): string; 7 | 8 | public wrapProductAsGift(): string { 9 | return 'Products are wrapped as a gift'; 10 | } 11 | 12 | public processOrder(isGift: boolean): string[] { 13 | this._isGift = isGift; 14 | const result: string[] = []; 15 | result.push(this.selectProducts()); 16 | result.push(this.payProducts()); 17 | if (this._isGift) { 18 | result.push(this.wrapProductAsGift()); 19 | } 20 | result.push(this.deliverProducts()); 21 | return result; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/app/21. Template Method/models/store.order.ts: -------------------------------------------------------------------------------- 1 | import { OrderTemplate } from './order.template'; 2 | 3 | export class StoreOrder extends OrderTemplate { 4 | public selectProducts(): string { 5 | return 'Customer chooses the item from shelf.'; 6 | } 7 | public payProducts(): string { 8 | return 'Pays at counter through cash.'; 9 | } 10 | 11 | public deliverProducts(): string { 12 | return 'Item delivered to in delivery counter.'; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/app/21. Template Method/template-method-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { TemplateMethodComponent } from './template-method/template-method.component'; 5 | 6 | const routes: Routes = [{ path: '', component: TemplateMethodComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class TemplateMethodRoutingModule {} 13 | -------------------------------------------------------------------------------- /src/app/21. Template Method/template-method.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { TemplateMethodRoutingModule } from './template-method-routing.module'; 5 | import { TemplateMethodComponent } from './template-method/template-method.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | import {MatCheckboxModule} from '@angular/material/checkbox'; 8 | import {FormsModule} from '@angular/forms'; 9 | 10 | @NgModule({ 11 | declarations: [TemplateMethodComponent], 12 | imports: [CommonModule, TemplateMethodRoutingModule, AngularMaterialModule, MatCheckboxModule, FormsModule] 13 | }) 14 | export class TemplateMethodModule {} 15 | -------------------------------------------------------------------------------- /src/app/21. Template Method/template-method/template-method.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Template Method Pattern 4 |

5 |
6 | 7 | 8 | 9 | As gift 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Ordering process 19 | 20 | 21 | 22 |
23 | - {{ logs }} 24 |
25 |
26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /src/app/21. Template Method/template-method/template-method.component.scss: -------------------------------------------------------------------------------- 1 | mat-card-header.mat-card-header { 2 | justify-content: center; 3 | } 4 | 5 | mat-card-content.gift { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | } 10 | 11 | mat-card-content { 12 | display: flex; 13 | flex-direction: column; 14 | align-items: flex-start; 15 | 16 | div { 17 | text-align: left; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/app/21. Template Method/template-method/template-method.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { OnlineOrder } from '../models/online.order'; 3 | import { StoreOrder } from '../models/store.order'; 4 | 5 | @Component({ 6 | selector: 'app-template-method', 7 | templateUrl: './template-method.component.html', 8 | styleUrls: ['./template-method.component.scss'] 9 | }) 10 | export class TemplateMethodComponent { 11 | 12 | // resource: https://www.geeksforgeeks.org/template-method-design-pattern/ 13 | 14 | public isGift: boolean; 15 | public listLogs: string[] = []; 16 | 17 | private onlineOrder: OnlineOrder; 18 | private storeOrder: StoreOrder; 19 | 20 | public btnOrderOnline(): void { 21 | this.onlineOrder = new OnlineOrder(); 22 | this.listLogs = this.onlineOrder.processOrder(this.isGift); 23 | } 24 | 25 | public btnOrderInStore(): void { 26 | this.storeOrder = new StoreOrder(); 27 | this.listLogs = this.storeOrder.processOrder(this.isGift); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/chain-of-responsibility-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { ChainOfResponsibilityComponent } from './chain-of-responsibility/chain-of-responsibility.component'; 5 | 6 | const routes: Routes = [{ path: '', component: ChainOfResponsibilityComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class ChainOfResponsibilityRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/chain-of-responsibility.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { ChainOfResponsibilityRoutingModule } from './chain-of-responsibility-routing.module'; 5 | import { ChainOfResponsibilityComponent } from './chain-of-responsibility/chain-of-responsibility.component'; 6 | import {AngularMaterialModule} from '../modules/angular-material.module'; 7 | import {FormsModule} from '@angular/forms'; 8 | 9 | 10 | @NgModule({ 11 | declarations: [ChainOfResponsibilityComponent], 12 | imports: [ 13 | CommonModule, 14 | ChainOfResponsibilityRoutingModule, 15 | AngularMaterialModule, 16 | FormsModule 17 | ] 18 | }) 19 | export class ChainOfResponsibilityModule { } 20 | -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/chain-of-responsibility/chain-of-responsibility.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Chain Of Responsibility Pattern 4 |

5 |

(CoR, Chain of Command)

6 |
7 | 8 | 9 | 10 | 11 | 12 |
{{ randomNumber }}
13 |
{{ result }}
14 |
15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/chain-of-responsibility/chain-of-responsibility.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/src/app/22. Chain of Responsibility/chain-of-responsibility/chain-of-responsibility.component.scss -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/chain-of-responsibility/chain-of-responsibility.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FiftyHandler, FiveHandler, HundredHandler, OneHandler, TenHandler, ThreeHandler, TwentyHandler } from '../models/handler.model'; 3 | 4 | @Component({ 5 | selector: 'app-chain-of-responsibility', 6 | templateUrl: './chain-of-responsibility.component.html', 7 | styleUrls: ['./chain-of-responsibility.component.scss'] 8 | }) 9 | export class ChainOfResponsibilityComponent { 10 | 11 | // inspired by https://refactoring.guru/design-patterns/chain-of-responsibility/typescript/example 12 | 13 | public randomNumber: number; 14 | public result: string; 15 | 16 | private hundredHandler: HundredHandler; 17 | private fiftyHandler: FiftyHandler; 18 | private twentyHandler: TwentyHandler; 19 | private tenHandler: TenHandler; 20 | private fiveHandler: FiveHandler; 21 | private threeHandler: ThreeHandler; 22 | private oneHandler: OneHandler; 23 | 24 | constructor() { 25 | this.randomNumber = 0; 26 | this.result = ''; 27 | this.handlerFactory(); 28 | } 29 | 30 | public btnCheckRandomNumber(): void { 31 | this.result = this.handleRandomNumber(); 32 | } 33 | 34 | private handleRandomNumber(): string { 35 | this.randomNumber = +(Math.random() * 110).toFixed(2); 36 | return this.hundredHandler.handle(this.randomNumber); 37 | } 38 | 39 | private handlerFactory(): void { 40 | this.hundredHandler = new HundredHandler(); 41 | this.fiftyHandler = new FiftyHandler(); 42 | this.twentyHandler = new TwentyHandler(); 43 | this.tenHandler = new TenHandler(); 44 | this.fiveHandler = new FiveHandler(); 45 | this.threeHandler = new ThreeHandler(); 46 | this.oneHandler = new OneHandler(); 47 | this.hundredHandler 48 | .setNext(this.fiftyHandler) 49 | .setNext(this.twentyHandler) 50 | .setNext(this.tenHandler) 51 | .setNext(this.fiveHandler) 52 | .setNext(this.threeHandler) 53 | .setNext(this.oneHandler); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/models/handler.abstract.ts: -------------------------------------------------------------------------------- 1 | import { Handler } from './handler.interface'; 2 | 3 | export abstract class AbstractHandler implements Handler { 4 | private nextHandler: Handler; 5 | 6 | public setNext(handler: Handler): Handler { 7 | this.nextHandler = handler; 8 | return handler; 9 | } 10 | 11 | public handle(request: number): string { 12 | if (this.nextHandler) { 13 | return this.nextHandler.handle(request); 14 | } 15 | 16 | return null; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/models/handler.interface.ts: -------------------------------------------------------------------------------- 1 | export interface Handler { 2 | setNext(handler: Handler): Handler; 3 | handle(request: number): string; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/22. Chain of Responsibility/models/handler.model.ts: -------------------------------------------------------------------------------- 1 | import { AbstractHandler } from './handler.abstract'; 2 | 3 | export class HundredHandler extends AbstractHandler { 4 | public handle(request: number): string { 5 | return request >= 100 ? 'number is bigger than 100' : super.handle(request); 6 | } 7 | } 8 | 9 | export class FiftyHandler extends AbstractHandler { 10 | public handle(request: number): string { 11 | return request >= 50 ? 'number is bigger than 50' : super.handle(request); 12 | } 13 | } 14 | 15 | export class TwentyHandler extends AbstractHandler { 16 | public handle(request: number): string { 17 | return request >= 20 ? 'number is bigger than 20' : super.handle(request); 18 | } 19 | } 20 | 21 | export class TenHandler extends AbstractHandler { 22 | public handle(request: number): string { 23 | return request >= 10 ? 'number is bigger than 10' : super.handle(request); 24 | } 25 | } 26 | 27 | export class FiveHandler extends AbstractHandler { 28 | public handle(request: number): string { 29 | return request >= 5 ? 'number is bigger than 5' : super.handle(request); 30 | } 31 | } 32 | 33 | export class ThreeHandler extends AbstractHandler { 34 | public handle(request: number): string { 35 | return request >= 3 ? 'number is bigger than 3' : super.handle(request); 36 | } 37 | } 38 | 39 | export class OneHandler extends AbstractHandler { 40 | public handle(request: number): string { 41 | return request >= 1 ? 'number is bigger than 1' : super.handle(request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/23. Interpreter/interpreter-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { InterpreterComponent } from './interpreter/interpreter.component'; 5 | 6 | const routes: Routes = [{ path: '', component: InterpreterComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class InterpreterRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/23. Interpreter/interpreter.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { InterpreterRoutingModule } from './interpreter-routing.module'; 5 | import { InterpreterComponent } from './interpreter/interpreter.component'; 6 | 7 | 8 | @NgModule({ 9 | declarations: [InterpreterComponent], 10 | imports: [ 11 | CommonModule, 12 | InterpreterRoutingModule 13 | ] 14 | }) 15 | export class InterpreterModule { } 16 | -------------------------------------------------------------------------------- /src/app/23. Interpreter/interpreter/interpreter.component.html: -------------------------------------------------------------------------------- 1 |

interpreter works!

2 | -------------------------------------------------------------------------------- /src/app/23. Interpreter/interpreter/interpreter.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/src/app/23. Interpreter/interpreter/interpreter.component.scss -------------------------------------------------------------------------------- /src/app/23. Interpreter/interpreter/interpreter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-interpreter', 5 | templateUrl: './interpreter.component.html', 6 | styleUrls: ['./interpreter.component.scss'] 7 | }) 8 | export class InterpreterComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 |
7 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | div.app-container { 2 | padding: 20px; 3 | display: flex; 4 | flex-direction: row; 5 | justify-content: center; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'] 7 | }) 8 | export class AppComponent { } 9 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { AppRoutingModule } from './app-routing.module'; 3 | import { AppComponent } from './app.component'; 4 | import { BrowserModule } from '@angular/platform-browser'; 5 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 6 | import { HttpClientModule } from '@angular/common/http'; 7 | import { AngularMaterialModule } from './modules/angular-material.module'; 8 | 9 | @NgModule({ 10 | declarations: [ 11 | AppComponent 12 | ], 13 | imports: [ 14 | BrowserModule, 15 | BrowserAnimationsModule, 16 | HttpClientModule, 17 | AppRoutingModule, 18 | AngularMaterialModule 19 | ], 20 | providers: [], 21 | bootstrap: [AppComponent] 22 | }) 23 | export class AppModule { } 24 | -------------------------------------------------------------------------------- /src/app/xx. components/Home/home-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { HomeComponent } from './home/home.component'; 5 | 6 | const routes: Routes = [{ path: '', component: HomeComponent }]; 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forChild(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class HomeRoutingModule { } 13 | -------------------------------------------------------------------------------- /src/app/xx. components/Home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { HomeRoutingModule } from './home-routing.module'; 5 | import { HomeComponent } from './home/home.component'; 6 | import {AngularMaterialModule} from '../../modules/angular-material.module'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [HomeComponent], 11 | imports: [ 12 | CommonModule, 13 | HomeRoutingModule, 14 | AngularMaterialModule 15 | ] 16 | }) 17 | export class HomeModule { } 18 | -------------------------------------------------------------------------------- /src/app/xx. components/Home/home/home.component.scss: -------------------------------------------------------------------------------- 1 | div.container { 2 | display: flex; 3 | flex-direction: row; 4 | } 5 | mat-card { 6 | text-align: center; 7 | margin: 15px; 8 | } 9 | 10 | mat-card-content { 11 | display: flex; 12 | flex-direction: column; 13 | } 14 | 15 | a { 16 | margin: 5px; 17 | } 18 | 19 | a:first-child { 20 | margin-top: 15px; 21 | } 22 | -------------------------------------------------------------------------------- /src/app/xx. components/Home/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-home', 5 | templateUrl: './home.component.html', 6 | styleUrls: ['./home.component.scss'] 7 | }) 8 | export class HomeComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Itchimonji/design-patterns-in-angular/61fdc88dfad268d411ed31906630311470677703/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Design Patterns In Angular 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { 4 | height: 100%; 5 | } 6 | body { 7 | margin: 0; 8 | padding: 0; 9 | font-family: Roboto, "Helvetica Neue", sans-serif; 10 | } 11 | 12 | div { 13 | text-align: center; 14 | } 15 | 16 | div.container { 17 | height: 100%; 18 | width: 100%; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | } 23 | 24 | div.content { 25 | display: flex; 26 | flex-direction: row; 27 | align-items: flex-start; 28 | } 29 | 30 | div.description { 31 | margin: 0 30px 30px; 32 | } 33 | 34 | div.flex-row { 35 | display: flex; 36 | flex-direction: row; 37 | justify-content: space-evenly; 38 | } 39 | 40 | mat-card { 41 | margin: 15px; 42 | max-width: 300px; 43 | } 44 | -------------------------------------------------------------------------------- /test-config.helper.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | type CompilerOptions = Partial<{ 4 | providers: any[]; 5 | useJit: boolean; 6 | preserveWhitespaces: boolean; 7 | }>; 8 | export type ConfigureFn = (testBed: typeof TestBed) => void; 9 | 10 | export const configureTests = (configure: ConfigureFn, compilerOptions: CompilerOptions = {}) => { 11 | const compilerConfig: CompilerOptions = { 12 | preserveWhitespaces: false, 13 | ...compilerOptions, 14 | }; 15 | 16 | const configuredTestBed = TestBed.configureCompiler(compilerConfig); 17 | 18 | configure(configuredTestBed); 19 | 20 | return configuredTestBed.compileComponents().then(() => configuredTestBed); 21 | }; 22 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts", 13 | "src/test.ts", 14 | "src/**/*.prod.ts" 15 | ], 16 | "exclude": [ 17 | "**/*.spec.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2017", 12 | "module": "esnext", 13 | "typeRoots": ["node_modules/@types"], 14 | "lib": ["es2017", "esnext.array", "esnext.asynciterable", "dom", "dom.iterable"], 15 | "skipLibCheck": true, 16 | "skipDefaultLibCheck": true, 17 | "baseUrl": "./", 18 | "noUnusedParameters": false, 19 | "noImplicitAny": false, 20 | "noImplicitThis": false, 21 | "strictFunctionTypes": false, 22 | "strictNullChecks": false, 23 | "strictPropertyInitialization": false, 24 | "strictBindCallApply": true, 25 | "resolveJsonModule": true, 26 | "paths": { 27 | "@abstract-factory": ["./src/app/01. Abstract Factory/*"], 28 | "@singleton": ["./src/app/02. Singleton/*"], 29 | "@prototype": ["./src/app/03. Prototype/*"], 30 | "@builder": ["./src/app/04. Builder/*"] 31 | } 32 | }, 33 | "angularCompilerOptions": { 34 | "fullTemplateTypeCheck": true, 35 | "strictInjectionParameters": true 36 | }, 37 | "exclude": ["node_modules", "tmp", "dist", "e2e/cypress"] 38 | } 39 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "node", 7 | "jest" 8 | ], 9 | "module": "commonjs", 10 | "emitDecoratorMetadata": true, 11 | "allowJs": true 12 | }, 13 | "files": [ 14 | "src/polyfills.ts" 15 | ], 16 | "include": [ 17 | "src/**/*.spec.ts", 18 | "src/**/*.d.ts" 19 | ] 20 | } 21 | --------------------------------------------------------------------------------