diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 4aef64b..e546f77 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -3,10 +3,10 @@
github: [Sean-Bradley]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: seanwasere
open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
+ko_fi: sean_bradley
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
-custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+custom: ['https://sean-bradley.medium.com/membership']# Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/LICENSE b/LICENSE
index b877eb2..e676d93 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,9 +1,12 @@
-All code, images, text and downloads from
+All code, images, text, videos and downloads from
Repository : https://github.com/Sean-Bradley/Design-Patterns-In-Python
Website : https://sbcode.net/python
Book : https://www.amazon.com/dp/B08XLJ8Z2J : ASIN B08XLJ8Z2J
-Videos : https://www.youtube.com/playlist?list=PLKWUX7aMnlEJzRvCXnwFEdk_WJDNjMDOo
+EBook : https://www.amazon.com/dp/B08Z282SBC : ASIN B08Z282SBC
+YouTube : https://www.youtube.com/playlist?list=PLKWUX7aMnlEJzRvCXnwFEdk_WJDNjMDOo
+Udemy : https://www.udemy.com/course/design-patterns-in-python/?referralCode=7493DBBBF97FF2B0D24D
+Skillshare : https://skl.sh/34SM2Xg
-Copyright (c) 2019-2021, Sean Bradley
-All rights reserved.
+Copyright (c) 2019-2022, Sean Bradley
+All rights reserved.
\ No newline at end of file
diff --git a/README.md b/README.md
index 3945459..1e77797 100644
--- a/README.md
+++ b/README.md
@@ -4,75 +4,89 @@ This repository focuses on the 23 famous GoF (Gang of Four) Design Patterns impl
It is supplementary to my book titled **Design Patterns In Python** (ASIN : B08XLJ8Z2J)
-
+
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
+
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
-
https://www.amazon.ca/dp/B08XLJ8Z2J
+
https://www.amazon.ca/dp/B08XLJ8Z2J
+
https://www.amazon.com.au/dp/B08XLJ8Z2J
+## Course Access
+
+There are 3 possible ways to access the video content in this course,
+
+1. Udemy : [https://www.udemy.com/course/design-patterns-in-python/?referralCode=7493DBBBF97FF2B0D24D](https://www.udemy.com/course/design-patterns-in-python/?referralCode=7493DBBBF97FF2B0D24D)
+ - Get **Udemy Discount Coupons** at [https://sbcode.net/coupons](https://sbcode.net/coupons)
+ - Certificate of Completion
+ - 30 Day Money Back Guarantee
+2. YouTube Membership : [https://www.youtube.com/channel/UCmUILI2AWt2MSUgPlZwFdOg/join](https://www.youtube.com/channel/UCmUILI2AWt2MSUgPlZwFdOg/join)
+ - Cancel Membership Anytime
+3. Book : [https://amzn.to/466lBN6](https://amzn.to/466lBN6) : ASIN B08XLJ8Z2J
+ - **Book** includes FREE Video Access Codes to view videos from the official documentation website at [https://sbcode.net/python/](https://sbcode.net/python/)
All the code examples in the book can be found in these pages.
-A Design Pattern is a description or template that can be repeatedly applied to a commonly recurring problem in software design.
+---
-A familiarity of Design Patterns will be very useful when planning, discussing, managing and documenting your applications from now on and into the future.
+**TIP**
-Also, throughout the book, as each design pattern is discussed and demonstrated using example code, I also introduce new python coding concepts with each new design pattern. So that as you progress through the book and try out the examples, you will also get experience and familiarity with some of the finer details of programming with python.
-
-So, in this book, you will learn about these 23 Design Patterns,
-
-* Creational
- - [Factory](factory)
- - [Abstract Factory](abstract_factory)
- - [Builder](builder)
- - [Prototype](prototype)
- - [Singleton](singleton)
-* Structural
- - [Decorator](decorator)
- - [Adapter](adapter)
- - [Facade](facade)
- - [Bridge](bridge)
- - [Composite](composite)
- - [Flyweight](flyweight)
- - [Proxy](proxy)
-* Behavioral
- - [Command](command)
- - [Chain of Responsibility](chain_of_responsibility)
- - [Observer Pattern](observer)
- - [Interpreter](interpreter)
- - [Iterator](iterator)
- - [Mediator](mediator)
- - [Memento](memento)
- - [State](state)
- - [Strategy](strategy)
- - [Template](template)
- - [Visitor](visitor)
+> [Design Patterns In python](https://www.amazon.com/dp/B08XLJ8Z2J) **(Paperback/Kindle)** includes Video Access Codes to view videos for FREE from the official documentation website at [https://sbcode.net/python/](https://sbcode.net/python/)
-## Pattern Types
+---
-In the list of patterns above, there are Creational, Structural and Behavioral patterns.
+**TIP**
-* **Creational** : Abstracts the instantiation process so that there is a logical separation between how objects are composed and finally represented.
-* **Structural** : Structural patterns focus more on how classed and objects are composed using the different structural techniques, and to form structures with more or altered flexibility.
-* **Behavioral** : Are concerned with the inner algorithms, process flow, the assignment of responsibilities and the intercommunication between objects.
+> Get **Udemy Discount Coupons** at [https://sbcode.net/coupons](https://sbcode.net/coupons)
-## Class Scope and Object Scope Patterns
+---
+
+## Overview
-Each pattern can be further specified whether it relates more specifically classes or instantiated objects.
+A Design Pattern is a description or template that can be repeatedly applied to a commonly recurring problem in software design.
+
+A familiarity of Design Patterns will be very useful when planning, discussing, managing and documenting your applications from now on and into the future.
-Class scope patterns deal more with relationships between classes and their subclasses.
+Also, throughout the book, as each design pattern is discussed and demonstrated using example code, I also introduce new python coding concepts with each new design pattern. So that as you progress through the book and try out the examples, you will also get experience and familiarity with some finer details of programming with python.
+
+So, in this book, you will learn about these 23 Design Patterns,
+
+- Creational
+ - [Factory](factory)
+ - [Abstract Factory](abstract_factory)
+ - [Builder](builder)
+ - [Prototype](prototype)
+ - [Singleton](singleton)
+- Structural
+ - [Decorator](decorator)
+ - [Adapter](adapter)
+ - [Facade](facade)
+ - [Bridge](bridge)
+ - [Composite](composite)
+ - [Flyweight](flyweight)
+ - [Proxy](proxy)
+- Behavioral
+ - [Command](command)
+ - [Chain of Responsibility](chain_of_responsibility)
+ - [Observer Pattern](observer)
+ - [Interpreter](interpreter)
+ - [Iterator](iterator)
+ - [Mediator](mediator)
+ - [Memento](memento)
+ - [State](state)
+ - [Strategy](strategy)
+ - [Template](template)
+ - [Visitor](visitor)
-Object scope patterns deal more with relationships that can be altered at runtime
+## Pattern Types
+
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
+
+## Class Scope and Object Scope Patterns
-| Pattern | Description | Scope | Type |
-|---------------------------------------------------------------------------------------------------|--------------------------------------------|--------|-------------|
-| Factory, Abstract Factory | Defers object creation to subclasses | Class | Creational |
-| Builder, Prototype, Singleton | Defers object creation to objects | Object | Creational |
-| Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy | Describes a way to assemble objects | Object | Structural |
-| Interpreter, Template | Describes algorithms and flow control | Class | Behavioral |
-| Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy, Visitor | Describes how groups of objects co-operate | Object | Behavioral |
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
diff --git a/abstract_factory/README.md b/abstract_factory/README.md
index 739019b..fe3f1c5 100644
--- a/abstract_factory/README.md
+++ b/abstract_factory/README.md
@@ -2,35 +2,25 @@
## Videos
-Section | Video Link
+Section | Video Links
-|-
-Overview |
-Example Use Case |
-Exception Handling |
+Abstract Factory Overview |
+Abstract Factory Use Case |
+Exception Handling |
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The Abstract Factory Pattern adds an abstraction layer over multiple other creational pattern implementations.
-
-To begin with, in simple terms, think if it as a Factory that can return Factories. Although you will find examples of it also begin used to return Builder, Prototypes, Singletons or other design pattern implementations.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Client**: The client application that calls the **Abstract Factory** and **Abstract Product** classes. It's the same process as the concrete creator in the [Factory](/factory#terminology) design pattern.
-
-* **Abstract Factory**: An interface to one of the Factories.
-
-* **Concrete Factory**: The Factory returned via the interface and contains methods or attributes to allow creating the product.
-
-* **Abstract Product**: The interface for the product within its own Factory.
-
-* **Concrete Product**: The object finally returned.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Abstract Factory UML Diagram
@@ -46,9 +36,7 @@ python ./abstract_factory/abstract_factory_concept.py
## Abstract Factory Example Use Case
-An example use case may be that you have a furniture shop front. You sell many different kinds of furniture. You sell chairs and tables. And they are manufactured at different factories using different unrelated processes that are not important for your concern. You only need the factory to deliver.
-
-You can create an extra module called `FurnitureFactory`, to handle the chair and table factories, thus removing the implementation details from the client.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Abstract Factory Example UML Diagram
@@ -72,7 +60,7 @@ Your Python code may produce errors. It happens to everybody. It is hard to fore
Use the `Try`, `Except` and optional `finally` keywords to manage error handling.
-In the example code, if no chair or table is returned, an `Exception` error is raised and it includes a text string that can be read and written to the console.
+In the example code, if no chair or table is returned, an `Exception` error is raised, and it includes a text string that can be read and written to the console.
Within your code you can use the `raise` keyword to trigger Python built in exceptions or even create your own.
@@ -81,9 +69,9 @@ def get_furniture(furniture):
"Static get_factory method"
try:
if furniture in ['SmallChair', 'MediumChair', 'BigChair']:
- return ChairFactory().get_chair(furniture)
+ return ChairFactory.get_chair(furniture)
if furniture in ['SmallTable', 'MediumTable', 'BigTable']:
- return TableFactory().get_table(furniture)
+ return TableFactory.get_table(furniture)
raise Exception('No Factory Found')
except Exception as _e:
print(_e)
@@ -109,7 +97,7 @@ The `try/except` allows the program to continue running, as can be verified by t
Alternatively, if your code didn't include the `try/except` and optional `finally` statements, the Python interpreter would return the error `NameError: name 'my_var' is not defined` and the program will crash at that line.
-Also note how the default Python inbuilt error starts with `NameError` . You can handle this specific error explicitly using an extra `except` keyword.
+Also note how the default Python inbuilt error starts with `NameError`. You can handle this specific error explicitly using an extra `except` keyword.
``` python
try:
@@ -129,10 +117,4 @@ Python Errors and Exceptions : [https://docs.python.org/3/tutorial/errors.html](
## Summary
-* Use when you want to provide a library of relatively similar products from multiple different factories.
-* You want the system to be independent of how the products are created.
-* It fulfills all of the same use cases as the Factory method, but is a factory for creational pattern type methods.
-* The client implements the abstract factory interface, rather than all the internal logic and Factories. This allows the possibility of creating a library that can be imported for using the Abstract Factory.
-* The Abstract Factory defers the creation of the final products/objects to its concrete factory subclasses.
-* You want to enforce consistent interfaces across products.
-* You want the possibility to exchange product families.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/abstract_factory/abstract_factory_concept.py b/abstract_factory/abstract_factory_concept.py
index 2cdde1b..7b6a105 100644
--- a/abstract_factory/abstract_factory_concept.py
+++ b/abstract_factory/abstract_factory_concept.py
@@ -22,9 +22,9 @@ def create_object(factory):
"Static get_factory method"
try:
if factory in ['aa', 'ab', 'ac']:
- return FactoryA().create_object(factory[1])
+ return FactoryA.create_object(factory[1])
if factory in ['ba', 'bb', 'bc']:
- return FactoryB().create_object(factory[1])
+ return FactoryB.create_object(factory[1])
raise Exception('No Factory Found')
except Exception as _e:
print(_e)
diff --git a/abstract_factory/furniture_factory.py b/abstract_factory/furniture_factory.py
index efd74f8..f52fdc9 100644
--- a/abstract_factory/furniture_factory.py
+++ b/abstract_factory/furniture_factory.py
@@ -13,9 +13,9 @@ def get_furniture(furniture):
"Static get_factory method"
try:
if furniture in ['SmallChair', 'MediumChair', 'BigChair']:
- return ChairFactory().get_chair(furniture)
+ return ChairFactory.get_chair(furniture)
if furniture in ['SmallTable', 'MediumTable', 'BigTable']:
- return TableFactory().get_table(furniture)
+ return TableFactory.get_table(furniture)
raise Exception('No Factory Found')
except Exception as _e:
print(_e)
diff --git a/adapter/README.md b/adapter/README.md
index 5a84175..36a5311 100644
--- a/adapter/README.md
+++ b/adapter/README.md
@@ -1,37 +1,27 @@
# Adapter Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Adapter Overview |
+Adapter Use Case |
+Python **isinstance()** Function |
+Python **time** Module |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-Sometimes classes have been written and you don't have the option of modifying their interface to suit your needs. This happens if the method you are calling is on a different system across a network, a library that you may import or generally something that is not viable to modify directly for your particular needs.
-
-The **Adapter** design pattern solves these problems:
-
-* How can a class be reused that does not have an interface that a client requires?
-* How can classes that have incompatible interfaces work together?
-* How can an alternative interface be provided for a class?
-
-You may have two classes that are similar, but they have different method signatures, so you create an Adapter over top of one of the method signatures so that it is easier to implement and extend in the client.
-
-An adapter is similar to the [Decorator](/decorator) in the way that it also acts like a wrapper to an object. It is also used at runtime; however, it is not designed to be used recursively.
-
-It is an alternative interface over an existing interface. It can also provide extra functionality that the interface being adapted may not already provide.
-
-The adapter is similar to the [Facade](/facade), but you are modifying the method signature, combining other methods and/or transforming data that is exchanged between the existing interface and the client.
-
-The Adapter is used when you have an existing interface that doesn't directly map to an interface that the client requires. So, then you create the Adapter which has a similar functional role, but with a new compatible interface.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Target**: The domain specific interface or class that needs to be adapted.
-* **Adapter Interface**: The interface of the target that the adapter will need to implement.
-* **Adapter**: The concrete adapter class containing the adaption process.
-* **Client**: The client application that will use the Adapter.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Adapter UML Diagram
@@ -39,11 +29,7 @@ The Adapter is used when you have an existing interface that doesn't directly ma
## Source Code
-In this concept source code, there are two classes, `ClassA` and `ClassB`, with different method signatures. Let's consider that `ClassA` provides the most compatible and preferred interface for the client.
-
-I can create objects of both classes in the client and it works. But before using each objects method, I need to do a conditional check to see which type of class it is that I am calling since the method signatures are different.
-
-It means that the client is doing extra work. Instead, I can create an Adapter interface for the incompatible `ClassB`, that reduces the need for the extra conditional logic.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -57,14 +43,7 @@ method B
## Example Use Case
-The example client can manufacture a **Cube** using different tools. Each solution is invented by a different company.
-The client user interface manages the Cube product by indicating the **width**, **height** and **depth**. This is compatible with the company A that produces the Cube tool, but not the company B that produces their own version of the Cube tool that uses a different interface with different parameters.
-
-In this example, the client will re-use the interface for company A's Cube and create a compatible Cube from company B.
-
-An adapter will be needed so that the same method signature can be used by the client without the need to ask company B to modify their Cube tool for our specific domains use case.
-
-My imaginary company needs to use both cube suppliers since there is a large demand for cubes and when one supplier is busy, I can then ask the other supplier.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -164,8 +143,4 @@ When executing [/adapter/cube_a.py](/adapter/cube_a.py) you will notice that the
## Summary
-* Use the Adapter when you want to use an existing class, but its interface does not match what you need.
-* The adapter adapts to the interface of its parent class for those situations when it is not viable to modify the parent class to be domain-specific for your use case.
-* Adapters will most likely provide an alternative interface over an existing object, class or interface, but it can also provide extra functionality that the object being adapted may not already provide.
-* An adapter is similar to a [Decorator](/decorator) except that it changes the interface to the object, whereas the decorator adds responsibility without changing the interface. This also allows the Decorator to be used recursively.
-* An adapter is similar to the [Bridge](/bridge) pattern and may look identical after the refactoring has been completed. However, the intent of creating the Adapter is different. The Bridge is a result of refactoring existing interfaces, whereas the Adapter is about adapting over existing interfaces that are not viable to modify due to many existing constraints. E.g., you don't have access to the original code or it may have dependencies that already use it and modifying it would affect those dependencies negatively.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/adapter/adapter_concept.py b/adapter/adapter_concept.py
index 420b295..ce43edf 100644
--- a/adapter/adapter_concept.py
+++ b/adapter/adapter_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"Adapter Concept Sample Code"
from abc import ABCMeta, abstractmethod
diff --git a/bridge/README.md b/bridge/README.md
index 030ba50..21be331 100644
--- a/bridge/README.md
+++ b/bridge/README.md
@@ -1,54 +1,27 @@
# Bridge Design Pattern
+## Videos
+
+| Section | Video Links |
+|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Bridge Overview |
|
+| Bridge Use Case |
|
+| Python **Tuple** |
|
+| Python **\*args** |
|
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Bridge pattern** is similar to the [Adapter](/adapter) pattern except in the intent that you developed it.
-
-The Bridge is an approach to refactor already existing code, whereas the Adapter creates an interface on top of existing code through existing available means without refactoring any existing code or interfaces.
-
-The motivation for converting your code to the Bridge pattern is that it may be tightly coupled. There is logic and abstraction close together that is limiting your choices in how you can extend your solution in the way that you need.
-
-E.g., you may have one Car class, that produces a very nice car. But you would like the option of varying the design a little, or outsourcing responsibility of creating the different components.
-
-The Bridge pattern is a process about separating abstraction and implementation, so this will give you plenty of new ways of using your classes.
-
-``` python
-CAR = Car()
-print(CAR)
-> Car has wheels and engine and windows and everything else.
-```
-
-But you would like to delegate the engine dynamically from a separate set of classes or solutions.
-
-``` python
-ENGINE = EngineA()
-CAR = Car(EngineA)
-```
-
-A Bridge didn't exist before, but since after the separation of interface and logic, each side can be extended independently of each other.
-
-Also, the application of a Bridge in your code should use composition instead of inheritance. This means that you assign the relationship at runtime, rather than hard coded in the class definition.
-
-I.e., `CAR = Car(EngineA)` rather than `class Car(EngineA):`
-
-A Bridge implementation will generally be cleaner than an Adapter solution that was bolted on. Since it involved refactoring existing code, rather than layering on top of legacy or third-party solutions that may not have been intended for your particular use case.
-
-You are the designer of the Bridge, but both approaches to the problem may work regardless.
-
-The implementer part of a Bridge, can have one or more possible implementations for each refined abstraction. E.g., The implementor can print to paper, or screen, or format for a web browser. And the abstraction side could allow for many permutations of every shape that you can imagine.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Abstraction Interface**: An interface implemented by the refined abstraction describing the common methods to implement.
-* **Refined Abstraction**: A refinement of an idea into another class or two. The classes should implement the Abstraction Interface and assign which concrete implementer.
-* **Implementer Interface**: The implementer interface that concrete implementers implement.
-* **Concrete Implementer**: The implementation logic that the refined abstraction will use.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Bridge UML Diagram
@@ -56,11 +29,7 @@ The implementer part of a Bridge, can have one or more possible implementations
## Source Code
-In the concept demonstration code, imagine that the classes were tightly coupled. The concrete class would print out some text to the console.
-
-After abstracting the class along a common ground, it is now more versatile. The implementation and has been separated from the abstraction and now it can print out the same text in two different ways.
-
-The befit now is that each refined abstraction and implementer can now be worked on independently without affecting the other implementations.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -74,15 +43,7 @@ c
## Example Use Case
-In this example, I draw a square and a circle. Both of these can be categorized as shapes.
-
-The shape is set up as the abstraction interface. The refined abstractions, `Square` and `Circle`, implement the `IShape` interface.
-
-When the Square and Circle objects are created, they are also assigned their appropriate implementers being `SquareImplementer` and `CircleImplementer` .
-
-When each shape's `draw` method is called, the equivalent method within their implementer is called.
-
-The Square and Circle are bridged and each implementer and abstraction can be worked on independently.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -95,18 +56,22 @@ python ./bridge/client.py
******
** **
* *
+
* *
* *
+
* *
** **
******
**************
+
* *
* *
* *
* *
* *
* *
+
**************
```
@@ -143,7 +108,7 @@ Outputs
A Python **Tuple** is similar to a [List](/builder#python-list). Except that the items in the Tuple are ordered, unchangeable and allow duplicates.
-A Tuple can be instantiated using the round brackets `()` or `tuple()`, verses `[]` for a [List](/builder#python-list) and `{}` for a [Set](/observer#python-set) or [Dictionary](/singleton#python-dictionary).
+A Tuple can be instantiated using the round brackets `()` or `tuple()` , verses `[]` for a [List](/builder#python-list) and `{}` for a [Set](/observer#python-set) or [Dictionary](/singleton#python-dictionary).
``` python
PS> python
@@ -156,7 +121,4 @@ PS> python
## Summary
-* Use when you want to separate a solution where the abstraction and implementation may be tightly coupled and you want to break it up into smaller conceptual parts.
-* Once you have added the bridge abstraction, you should be able to extend each side of it separately without breaking the other.
-* Also, once the bridge abstraction exists, you can more easily create extra concrete implementations for other similar products that may also happen to be split across similar conceptual lines.
-* The Bridge pattern is similar to the adapter pattern except in the intent that you developed it. The bridge is an approach to refactor already existing code, whereas the adapter adapts to the existing code through its existing interfaces and methods without changing the internals.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/bridge/bridge_concept.py b/bridge/bridge_concept.py
index 2fea67d..3ba44b8 100644
--- a/bridge/bridge_concept.py
+++ b/bridge/bridge_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"Bridge Pattern Concept Sample Code"
from abc import ABCMeta, abstractmethod
diff --git a/builder/README.md b/builder/README.md
index 0ba0bc0..1016ae9 100644
--- a/builder/README.md
+++ b/builder/README.md
@@ -2,35 +2,25 @@
## Videos
-Section | Video Link
+Section | Video Links
-|-
-Overview |
-Example Use Case |
-Lists |
+Builder Overview |
+Builder Use Case |
+Python **List** |
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The Builder Pattern is a creational pattern whose intent is to separate the construction of a complex object from its representation so that you can use the same construction process to create different representations.
-
-The Builder Pattern tries to solve,
-
-* How can a class create different representations of a complex object?
-* How can a class that includes creating a complex object be simplified?
-
-The Builder and Factory patterns are very similar in the fact they both instantiate new objects at runtime. The difference is when the process of creating the object is more complex, so rather than the Factory returning a new instance of `ObjectA`, it calls the builders director constructor method `ObjectA.construct()` that goes through a more complex construction process involving several steps. Both return an Object/Product.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Product**: The Product being built.
-* **Builder**: Builds the concrete product. Implements the `IBuilder` interface.
-* **Builder Interface**: The Interface that the Concrete builder should implement.
-* **Director**: Has a `construct()` method which when called creates a customized product.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Builder UML Diagram
@@ -38,9 +28,7 @@ The Builder and Factory patterns are very similar in the fact they both instanti
## Source Code
-1. Client creates the **Director**.
-2. The Client calls the Directors `construct()` method that manages each step of the build process.
-3. The Director returns the product to the client or alternatively could also provide a method for the client to retrieve it later.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -51,13 +39,7 @@ python ./builder/builder_concept.py
## Example Use Case
-Using the Builder Pattern in the context of a House Builder.
-
-There are multiple directors that can create their own complex objects.
-
-Note that in the `IglooDirector` class, not all of the methods of the `HouseBuilder` were called.
-
-The builder can construct complex objects in any order and include/exclude whichever parts it likes.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -131,7 +113,4 @@ This line, creates a list at runtime including the strings 'SmallChair', 'Medium
## Summary
-* The Builder pattern is a creational pattern that is used to create more complex objects than you'd expect from a factory.
-* The Builder pattern should be able to construct complex objects in any order and include/exclude whichever available components it likes.
-* For different combinations of products than can be returned from a Builder, use a specific Director to create the bespoke combination.
-* You can use an [Abstract Factory](/abstract_factory) to add an abstraction between the client and Director.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/builder/builder_concept.py b/builder/builder_concept.py
index cf674c8..676f3ee 100644
--- a/builder/builder_concept.py
+++ b/builder/builder_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"Builder Concept Sample Code"
from abc import ABCMeta, abstractmethod
diff --git a/chain_of_responsibility/README.md b/chain_of_responsibility/README.md
index 320495f..23537c5 100644
--- a/chain_of_responsibility/README.md
+++ b/chain_of_responsibility/README.md
@@ -1,28 +1,27 @@
# Chain of Responsibility Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Chain of Responsibility |
+Use Case |
+Python Floor Division |
+Accepting User Input |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-**Chain of Responsibility** pattern is a behavioral pattern used to achieve loose coupling in software design.
-
-In this pattern, an object is passed to a **Successor**, and depending on some kind of logic, will or won't be passed onto another successor and processed. There can be any number of different successors and successors can be re-processed recursively.
-
-This process of passing objects through multiple successors is called a chain.
-
-The object that is passed between each successor does not know about which successor will handle it. It is an independent object that may or may not be processed by a particular successor before being passed onto the next.
-
-The chain that the object will pass through is normally dynamic at runtime, although you can hard code the order or start of the chain, so each successor will need to comply with a common interface that allows the object to be received and passed onto the next successor.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Handler Interface**: A common interface for handling and passing objects through each successor.
-* **Concrete Handler**: The class acting as the **Successor** handling the requests and passing onto the next.
-* **Client**: The application or class that initiates the call to the first concrete handler (successor) in the chain.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Chain of Responsibility UML Diagram
@@ -30,7 +29,7 @@ The chain that the object will pass through is normally dynamic at runtime, alth
## Source Code
-In this concept code, a chain is created with a default first successor. A number is passed to a successor, which then does a random test, and depending on the result will modify the number and then pass it onto the next successor. The process is randomized and will end at some point when there are no more successors designated.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -48,11 +47,7 @@ Finished result = -1.5
## Example Use Case
-In the ATM example below, the chain is hard coded in the client first to dispense amounts of £50s, then £20s and then £10s in order.
-
-This default chain order helps to ensure that the minimum number of notes will be dispensed. Otherwise, it might dispense 5 x £10 when it would have been better to dispense 1 x £50.
-
-Each successor may be re-called recursively for each denomination depending on the value that was requested for withdrawal.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -116,10 +111,4 @@ See PEP-3111 : [https://www.python.org/dev/peps/pep-3111/](https://www.python.or
## Summary
-* The object will propagate through the chain until fully processed.
-* The object does not know that successor or how many will process it.
-* The next successor in the chain is chosen dynamically at runtime depending on logic from the current successor.
-* Successors implement a common interface that makes them work independently of each other, so that they can be used recursively or possibly in a different order.
-* A user wizard, or dynamic questionnaire are other common use cases for the chain of responsibility pattern.
-* The chain of responsibility and [Composite](/composite) patterns are often used together because of their similar approach to hierarchy and possible re-ordering. The Composites parent/child relationship is set in an object's property by a process outside of the class and can be changed at runtime. While with the Chain of Responsibility, each successor runs a dynamic algorithm internally, to decide which successor is next in line.
-* The chain can be fully dynamically created, or it can be set as a default with the possibility of changing at runtime.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/coding-conventions.md b/coding-conventions.md
index 410dee4..5c8de04 100644
--- a/coding-conventions.md
+++ b/coding-conventions.md
@@ -21,7 +21,7 @@ You can also enter Python code directly into the Python Interactive Console by t
``` python
PS> python
-Python 3.9.1 (tags/v3.9.1:1e5d33e, Dec 7 2020, 17:08:21) [MSC ...
+Python 3.10.1 (tags/v3.10.1:2cd268a, Dec 6 2021, 19:10:37) [MSC ...
Type "help", "copyright", "credits" or "license" for more information.
>>>
```
diff --git a/command/README.md b/command/README.md
index 7945c85..9835591 100644
--- a/command/README.md
+++ b/command/README.md
@@ -1,41 +1,26 @@
# Command Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Command Overview |
+Command Use Case |
+Single Leading Underscore |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Command** pattern is a behavioral design pattern, in which an abstraction exists between an object that invokes a command, and the object that performs it.
-
-E.g., a button will call the **Invoker**, that will call a pre-registered **Command**, that the **Receiver** will perform.
-
-A Concrete Class will delegate a request to a command object, instead of implementing the request directly.
-
-Using a command design pattern allows you to separate concerns and to solve problems of the concerns independently of each other.
-
-E.g., logging the execution of a command and its outcome.
-
-The command pattern is a good solution for implementing UNDO/REDO functionality into your application.
-
-Uses:
-
-* GUI Buttons, menus
-* Macro recording
-* Multi-level undo/redo
-* Networking - send whole command objects across a network, even as a batch
-* Parallel processing or thread pools
-* Transactional behavior
-* Wizards
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Receiver**: The object that will receive and execute the command.
-* **Invoker**: The object that sends the command to the receiver. E.g., A button.
-* **Command Object**: Itself, an object, that implements an execute, or action method, and contains all required information to execute it.
-* **Client**: The application or component that is aware of the Receiver, Invoker and Commands.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Command Pattern UML Diagram
@@ -43,15 +28,7 @@ Uses:
## Source Code
-The Client instantiates a Receiver that accepts certain commands.
-
-The Client then creates two Command objects that will call one of the specific commands on the Receiver.
-
-The Client then creates an Invoker, E.g., a user interface with buttons, and registers both Commands into the Invokers dictionary of commands.
-
-The Client doesn't call the receivers commands directly, but the via the Invoker, which then calls the registered Command objects `execute()` method.
-
-This abstraction between the invoker, command and receiver, allows the Invoker to add extra functionality such as history, replay, UNDO/REDO, logging, alerting and any other useful things that may be required.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -65,13 +42,7 @@ Executing Command 2
## Example Use Case
-This will be a smart light switch.
-
-This light switch will keep a history of each time one of its commands was called.
-
-And it can replay its commands.
-
-A smart light switch could be extended in the future to be called remotely or automated depending on sensors.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -107,7 +78,4 @@ It is just a useful construct that you will see developers use as a recommendati
## Summary
-* State should not be managed in the Command object itself.
-* There can be one or more Invokers which can execute the Command at a later time.
-* The Command object is especially useful if you want to UNDO/REDO commands at later time.
-* The Command pattern is similar to the [Memento](/memento) pattern in the way that it can also be used for UNDO/REDO purposes. However, the Memento pattern is about recording and replacing the state of an object, whereas the Command pattern executes a predefined command. E.g., Draw, Turn, Resize, Save, etc.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/command/command_concept.py b/command/command_concept.py
index 07e0fee..e16231b 100644
--- a/command/command_concept.py
+++ b/command/command_concept.py
@@ -1,3 +1,4 @@
+# pylint: disable=arguments-differ
"The Command Pattern Concept"
from abc import ABCMeta, abstractmethod
diff --git a/composite/README.md b/composite/README.md
index f516ab3..7a9f7b0 100644
--- a/composite/README.md
+++ b/composite/README.md
@@ -1,30 +1,26 @@
# Composite Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Composite Overview |
+Composite Use Case |
+Conditional Expressions |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Composite** design pattern is a structural pattern useful for hierarchal management.
-
-The Composite design pattern,
-
-* allows you to represent individual entities(leaves) and groups of leaves at the same.
-* is a structural design pattern that lets you compose objects into a changeable tree structure.
-* is great if you need the option of swapping hierarchal relationships around.
-* allows you to add/remove components to the hierarchy.
-* provides flexibility of structure
-
-Examples of using the Composite Design Pattern can be seen in a filesystem directory structure where you can swap the hierarchy of files and folders, and also in a drawing program where you can group, un-group, transform objects and change multiple objects at the same time.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Component Interface**: The interface that all leaves and composites should implement.
-* **Leaf**: A single object that can exist inside or outside of a composite.
-* **Composite**: A collections of leaves and/or other composites.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Composite UML Diagram
@@ -32,15 +28,7 @@ Examples of using the Composite Design Pattern can be seen in a file
## Source Code
-In this concept code, two leaves are created, `LEAF_A` and `LEAF_B`, and two composites are created, `COMPOSITE_1` and `COMPOSITE_2` .
-
-`LEAF_A` is attached to `COMPOSITE_1` .
-
-Then I change my mind and attach `LEAF_A` to `COMPOSITE_2` .
-
-I then attach `COMPOSITE_1` to `COMPOSITE_2` .
-
-`LEAF_B` is not attached to composites.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -60,13 +48,7 @@ COMPOSITE_2 id:2050574298128
## Composite Example Use Case
-Demonstration of a simple in memory hierarchal file system.
-
-A root object is created that is a composite.
-
-Several files (leaves) are created and added to the root folder.
-
-More folders (composites) are created, and more files are added, and then the hierarchy is reordered.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Composite Example UML Diagram
@@ -142,7 +124,4 @@ Visit [https://docs.python.org/3/reference/expressions.html#conditional-expressi
## Summary
-* The Composite design pattern allows you to structure components in a manageable hierarchal order.
-* It provides flexibility of structure since you can add/remove and reorder components.
-* File explorer on windows is a very good example of the composite design pattern in use.
-* Any system where you need to offer at runtime the ability to group, un-group, modify multiple objects at the same time, would benefit from the composite design pattern structure. Programs that allow you to draw shapes and graphics will often also use this structure as well.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/composite/composite_concept.py b/composite/composite_concept.py
index 7d16268..b61280e 100644
--- a/composite/composite_concept.py
+++ b/composite/composite_concept.py
@@ -1,3 +1,4 @@
+# pylint: disable=arguments-differ
"The Composite pattern concept"
from abc import ABCMeta, abstractmethod
diff --git a/decorator/README.md b/decorator/README.md
index cfd5243..31c7f86 100644
--- a/decorator/README.md
+++ b/decorator/README.md
@@ -2,38 +2,26 @@
## Videos
-Section | Video Link
+Section | Video Links
-|-
-Overview |
-Example Use Case |
-\__str\__ Dunder |
-getattr() Method |
+Decorator Overview |
+Decorator Use Case |
+**\__str\__** Dunder Method|
+Python **getattr()** Method |
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **decorator pattern** is a structural pattern, that allows you to attach additional responsibilities to an object at runtime.
-
-The decorator pattern is used in both the Object Oriented and Functional paradigms.
-
-The decorator pattern is different than the Python language feature of [Python Decorators](https://www.python.org/dev/peps/pep-0318/#on-the-name-decorator) in its syntax and complete purpose. It is a similar concept in the way that it is a wrapper, but it also can be applied at runtime dynamically.
-
-The decorator pattern adds extensibility without modifying the original object.
-
-The decorator forwards requests to the enclosed object and can perform extra actions.
-
-You can nest decorators recursively.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Component Interface**: An interface for objects.
-* **Component**: The object that may be decorated.
-* **Decorator**: The class that applies the extra responsibilities to the component being decorated. It also implements the same component interface.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Builder UML Diagram
@@ -49,13 +37,7 @@ Decorator Method(Component Method)
## Example Use Case
-Let's create a custom class called `Value` that will hold a number.
-
-Then add decorators that allow addition (`Add`) and subtraction (`Sub`) to a number (`Value`).
-
-The `Add` and `Sub` decorators can accept integers directly, a custom `Value` object or other `Add` and `Sub` decorators.
-
-`Add`, `Sub` and `Value` all implement the `IValue` interface and can be used recursively.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -151,9 +133,4 @@ The `__str__` dunder was also overridden in the [/prototype/prototype_concept.py
## Summary
-* Use the decorator when you want to add responsibilities to objects dynamically without affecting the inner object.
-* You want the option to later remove the decorator from an object in case you no longer need it.
-* It is an alternative method to creating multiple combinations of subclasses. I.e., Instead of creating a subclass with all combinations of objects A, B, C in any order, and including/excluding objects, you could create 3 objects that can decorate each other in any order you want. E.g., (D(A(C))) or (B(C)) or (A(B(A(C)))
-* The decorator, compared to using static inheritance to extend, is more flexible since you can easily add/remove the decorators at runtime. E.g., use in a recursive function.
-* A decorator supports recursive composition. E.g., halve(halve(number))
-* A decorator shouldn't modify the internal objects data or references. This allows the original object to stay intact if the decorator is later removed.
\ No newline at end of file
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/decorator/decorator_concept.py b/decorator/decorator_concept.py
index 7bb2708..617add5 100644
--- a/decorator/decorator_concept.py
+++ b/decorator/decorator_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"Decorator Concept Sample Code"
from abc import ABCMeta, abstractmethod
diff --git a/facade/README.md b/facade/README.md
index 15c12f7..242a2d6 100644
--- a/facade/README.md
+++ b/facade/README.md
@@ -1,18 +1,23 @@
# Facade Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Facade Overview |
+Facade Use Case |
+Python **Decimal** |
+Python Type Hints |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-Sometimes you have a system that becomes quite complex over time as more features are added or modified. It may be useful to provide a simplified API over it. This is the facade pattern.
-
-The facade pattern essentially is an alternative, reduced or simplified interface to a set of other interfaces, abstractions and implementations within a system that may be full of complexity and/or tightly coupled.
-
-It can also be considered as a higher-level interface that shields the consumer from the unnecessary low-level complications of integrating into many subsystems.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Facade UML Diagram
@@ -32,9 +37,7 @@ B
## Example Use Case
-This is an example of a game engine API. The facade layer is creating one streamlined interface consisting of several methods from several larger API backend systems.
-
-The client could connect directly to each subsystems API and implement its authentication protocols, specific methods, etc. While it is possible, it would be quite a lot of consideration for each of the development teams, so the facade API unifies the common methods which becomes much less overwhelming for each new the client developer to integrate into.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -167,9 +170,4 @@ Found 2 errors in 2 files (checked 1 source file)
## Summary
-* Use when you want to provide a simple interface to a complex subsystem.
-* You want to layer your subsystems into an abstraction that is easier to understand.
-* [Abstract Factory](/abstract_factory) and Facade can be considered very similar. An Abstract Factory is about creating in interface over several creational classes of similar objects, whereas the Facade is more like an API layer over many creational, structural and/or behavioral patterns.
-* The [Mediator](/mediator) is similar to the Facade in the way that it abstracts existing classes. The Facade is not intended to modify, load balance or apply any extra logic. A subsystem does not need to consider that existence of the facade, it would still work without it.
-* A Facade is a minimal interface that could also be implemented as a [Singleton](/singleton).
-* A Facade is an optional layer that does not alter the subsystem. The subsystem does not need to know about the Facade, and could even be used by many other facades created for different audiences.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/facade/game_api.py b/facade/game_api.py
index ab16506..32e6159 100644
--- a/facade/game_api.py
+++ b/facade/game_api.py
@@ -34,6 +34,7 @@ def submit_entry(user_id: str, entry: Decimal) -> bool:
return GameEngine().submit_entry(user_id, entry)
@staticmethod
- def register_user(value: dict[str, str]) -> str:
+ def register_user(value: dict[str, str]) -> str: # Python 3.9
+ # def register_user(value) -> str: # Python 3.8 and earlier
"register a new user and returns the new id"
return Users.register_user(value)
diff --git a/facade/game_engine.py b/facade/game_engine.py
index dbfeaba..3dd6ecd 100644
--- a/facade/game_engine.py
+++ b/facade/game_engine.py
@@ -10,7 +10,8 @@ class GameEngine():
_instance = None
_start_time: int = 0
_clock: int = 0
- _entries: list[tuple[str, Decimal]] = []
+ _entries: list[tuple[str, Decimal]] = [] # Python 3.9
+ # _entries = [] # Python 3.8 or earlier
_game_open = True
def __new__(cls):
diff --git a/facade/reports.py b/facade/reports.py
index c9a90cc..0f86456 100644
--- a/facade/reports.py
+++ b/facade/reports.py
@@ -4,7 +4,8 @@
class Reports():
"A Singleton Dictionary of Reported Events"
- _reports: dict[int, tuple[float, str]] = {}
+ _reports: dict[int, tuple[float, str]] = {} # Python 3.9
+ # _reports = {} # Python 3.8 or earlier
_row_id = 0
def __new__(cls):
diff --git a/facade/users.py b/facade/users.py
index dceb9dd..f199bee 100644
--- a/facade/users.py
+++ b/facade/users.py
@@ -6,13 +6,15 @@
class Users():
"A Singleton Dictionary of Users"
- _users: dict[str, dict[str, str]] = {}
+ _users: dict[str, dict[str, str]] = {} # Python 3.9
+ # _users = {} # Python 3.8 or earlier
def __new__(cls):
return cls
@classmethod
- def register_user(cls, new_user: dict[str, str]) -> str:
+ def register_user(cls, new_user: dict[str, str]) -> str: # Python 3.9
+ # def register_user(cls, new_user) -> str: # Python 3.8 or earlier
"register a user"
if not new_user["user_name"] in cls._users:
# generate really complicated unique user_id.
diff --git a/facade/wallets.py b/facade/wallets.py
index f5b0342..996c610 100644
--- a/facade/wallets.py
+++ b/facade/wallets.py
@@ -5,7 +5,8 @@
class Wallets():
"A Singleton Dictionary of User Wallets"
- _wallets: dict[str, Decimal] = {}
+ _wallets: dict[str, Decimal] = {} # Python 3.9
+ # _wallets = {} # Python 3.8 or earlier
def __new__(cls):
return cls
diff --git a/factory/README.md b/factory/README.md
index 3e15c3d..4a6f2b9 100644
--- a/factory/README.md
+++ b/factory/README.md
@@ -2,45 +2,25 @@
## Videos
-Section | Video Link
+Section | Video Links
-|-
-Overview |
-Example Use Case |
-ABCMeta |
+Factory Overview |
+Factory Use Case |
+**ABCMeta** Module |
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-When developing code, you may instantiate objects directly in methods or in classes. While this is quite normal, you may want to add an extra abstraction between the creation of the object and where it is used in your project.
-
-You can use the **Factory** pattern to add that extra abstraction. The Factory pattern is one of the easiest patterns to understand and implement.
-
-Adding an extra abstraction will also allow you to dynamically choose classes to instantiate based on some kind of logic.
-
-Before the abstraction, your class or method would directly create a concrete class. After adding the factory abstraction, the concrete class is now created outside of the current class/method, and now in a subclass.
-
-Imagine an application for designing houses and the house has a chair already added on the floor by default. By adding the factory pattern, you could give the option to the user to choose different chairs, and how many at runtime. Instead of the chair being hard coded into the project when it started, the user now has the option to choose.
-
-Adding this extra abstraction also means that the complications of instantiating extra objects can now be hidden from the class or method that is using it.
-
-This separation also makes your code easier to read and document.
-
-The Factory pattern is really about adding that extra abstraction between the object creation and where it is used. This gives you extra options that you can more easily extend in the future.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Concrete Creator**: The client application, class or method that calls the Creator (Factory method).
-
-* **Product Interface**: The interface describing the attributes and methods that the Factory will require in order to create the final product/object.
-
-* **Creator**: The Factory class. Declares the Factory method that will return the object requested from it.
-
-* **Concrete Product**: The object returned from the Factory. The object implements the Product interface.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Factory UML Diagram
@@ -48,11 +28,7 @@ The Factory pattern is really about adding that extra abstraction between the ob
## Source Code
-In this concept example, the client wants an object named `b`
-
-Rather than creating `b` directly in the client, it asks the creator (factory) for the object instead.
-
-The factory finds the relevant class using some kind of logic from the attributes of the request. It then asks the subclass to instantiate the new object which it then returns as a reference back to the client asking for it.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -63,11 +39,7 @@ ConcreteProductB
## Example Use Case
-An example use case is a user interface where the user can select from a menu of items, such as chairs.
-
-The user has been given a choice using some kind of navigation interface, and it is unknown what choice, or how many the user will make until the application is actually running and the user starts using it.
-
-So, when the user selected the chair, the factory then takes some property involved with that selection, such as an ID, Type or other attribute and then decides which relevant subclass to instantiate in order to return the appropriate object.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Factory Example UML Diagram
@@ -119,12 +91,6 @@ Note that in all my code examples, the abstract classes are prefixed with a capi
See PEP 3119 : [https://www.python.org/dev/peps/pep-3119/](https://www.python.org/dev/peps/pep-3119/)
-
## Summary
-* The Factory Pattern is an Interface that defers the creation of the final object to a subclass.
-* The Factory pattern is about inserting another layer/abstraction between instantiating an object and where in your code it is actually used.
-* It is unknown what or how many objects will need to be created until runtime.
-* You want to localize knowledge of the specifics of instantiating a particular object to the subclass so that the client doesn't need to be concerned about the details.
-* You want to create an external framework, that an application can import/reference, and hide the details of the specifics involved in creating the final object/product.
-* The unique factor that defines the Factory pattern, is that your project now defers the creation of objects to the subclass that the factory had delegated it to.
\ No newline at end of file
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/factory/client.py b/factory/client.py
index 0a93224..c4f9bc5 100644
--- a/factory/client.py
+++ b/factory/client.py
@@ -3,5 +3,5 @@
from chair_factory import ChairFactory
# The Client
-CHAIR = ChairFactory().get_chair("SmallChair")
+CHAIR = ChairFactory.get_chair("SmallChair")
print(CHAIR.get_dimensions())
diff --git a/factory/factory_concept.py b/factory/factory_concept.py
index 0c17e2a..6dbb529 100644
--- a/factory/factory_concept.py
+++ b/factory/factory_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"The Factory Concept"
from abc import ABCMeta, abstractmethod
@@ -58,5 +59,5 @@ def create_object(some_property):
# The Client
-PRODUCT = Creator().create_object('b')
+PRODUCT = Creator.create_object('b')
print(PRODUCT.name)
diff --git a/flyweight/README.md b/flyweight/README.md
index 589c8f7..e0fbbc2 100644
--- a/flyweight/README.md
+++ b/flyweight/README.md
@@ -1,40 +1,26 @@
# Flyweight Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Flyweight Overview |
+Flyweight Use Case |
+String Justification |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-**Fly** in the term **Flyweight** means light/not heavy.
-
-Instead of creating thousands of objects that share common attributes, and result in a situation where a large amount of memory or other resources are used, you can modify your classes to share multiple instances simultaneously by using some kind of reference to the shared object instead.
-
-The best example to describe this is a document containing many words and sentences and made up of many letters. Rather than storing a new object for each individual letter describing its font, position, color, padding and many other potential things. You can store just a lookup id of a character in a collection of some sort and then dynamically create the object with its proper formatting etc., only as you need to.
-
-This approach saves a lot of memory at the expense of using some extra CPU instead to create the object at presentation time.
-
-The Flyweight pattern, describes how you can share objects rather than creating thousands of almost repeated objects unnecessarily.
-
-A Flyweight acts as an independent object in any number of contexts. A context can be a cell in a table, or a div on a html page. A context is using the Flyweight.
-
-You can have many contexts, and when they ask for a Flyweight, they will get an object that may already be shared amongst other contexts, or already within it self somewhere else.
-
-When describing flyweights, it is useful to describe it in terms of intrinsic and extrinsic attributes.
-
-**Intrinsic** (in or including) are the attributes of a flyweight that are internal and unique from the other flyweights. E.g., a new flyweight for every letter of the alphabet. Each letter is intrinsic to the flyweight.
-
-**Extrinsic** (outside or external) are the attributes that are used to present the flyweight in terms of the context where it will be used. E.g., many letters in a string can be right aligned with each other. The extrinsic property of each letter is the new positioning of its X and Y on a grid.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Flyweight Interface**: An interface where a flyweight receives its extrinsic attributes.
-* **Concrete Flyweight**: The flyweight object that stores the intrinsic attributes and implements the interface to apply extrinsic attributes.
-* **Unshared Flyweights**: Not all flyweights will be shared, the flyweight enables sharing, not enforcing it. It also possible that flyweights can share other flyweights but still not yet be used in any contexts anywhere.
-* **Flyweight Factory**: Creates and manages flyweights at runtime. It reuses flyweights in memory, or creates a new one in demand.
-* **Client**: The client application that uses and creates the Flyweight.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Flyweight UML Diagram
@@ -42,11 +28,7 @@ When describing flyweights, it is useful to describe it in terms of intrinsic an
## Source Code
-A context is created using the string `abracadabra`.
-
-As it is output, it asks the Flyweight factory for the next character. The Flyweight factory will either return an existing Flyweight, or create a new one before returning it.
-
-`abracadabra` has many re-used characters, so only 5 flyweights needed to be created.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -59,11 +41,7 @@ FlyweightFactory has 5 flyweights
## Example Use Case
-In this example, I create a dynamic table with 3 rows and 3 columns each. The columns are then filled with some kind of text, and also chosen to be left, right or center aligned.
-
-The letters are the flyweights and only a code indicating the letter is stored. The letters and numbers are shared many times.
-
-The columns are the contexts and they pass the extrinsic vales describing the combination of letters, the justification left, right or center, and the width of the table column that is then used for the space padding.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -108,11 +86,4 @@ eg,
## Summary
-* Clients should access Flyweight objects only the through a `FlyweightFactory` object to ensure that they are shared.
-* Intrinsic values are stored internally in the Flyweight.
-* Extrinsic values are passed to the Flyweight and customise it depending on the context.
-* Implementing the flyweight is a balance between storing all objects in memory, versus storing small unique parts in memory, and potentially calculating extrinsic values in the context objects.
-* Use the flyweight to save memory when it is beneficial. The offset is that extra CPU may be required during calculating and passing extrinsic values to the flyweights.
-* The flyweight reduces memory footprint because it shares objects and allows the possibility of dynamically creating extrinsic attributes.
-* The contexts will generally calculate the extrinsic values used by the flyweights, but it is not necessary. Values can be stored or referenced from other objects if necessary.
-* When architecting the flyweight, start with considering which parts of a common object may be able to be split and applied using extrinsic attributes.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/flyweight/flyweight.py b/flyweight/flyweight.py
index 63667e3..e7e33de 100644
--- a/flyweight/flyweight.py
+++ b/flyweight/flyweight.py
@@ -4,5 +4,5 @@
class Flyweight(): # pylint: disable=too-few-public-methods
"The Flyweight that contains an intrinsic value called code"
- def __init__(self, code: int) -> None:
+ def __init__(self, code: str) -> None:
self.code = code
diff --git a/flyweight/flyweight_concept.py b/flyweight/flyweight_concept.py
index fe17bcc..daa478f 100644
--- a/flyweight/flyweight_concept.py
+++ b/flyweight/flyweight_concept.py
@@ -9,20 +9,21 @@ class IFlyweight():
class Flyweight(IFlyweight):
"The Concrete Flyweight"
- def __init__(self, code: int) -> None:
+ def __init__(self, code: str) -> None:
self.code = code
class FlyweightFactory():
"Creating the FlyweightFactory as a singleton"
- _flyweights: dict[int, Flyweight]= {}
+ _flyweights: dict[str, Flyweight] = {} # Python 3.9
+ # _flyweights = {} # Python 3.8 or earlier
def __new__(cls):
return cls
@classmethod
- def get_flyweight(cls, code: int) -> Flyweight:
+ def get_flyweight(cls, code: str) -> Flyweight:
"A static method to get a flyweight based on a code"
if not code in cls._flyweights:
cls._flyweights[code] = Flyweight(code)
diff --git a/flyweight/flyweight_factory.py b/flyweight/flyweight_factory.py
index 81b9727..9206d38 100644
--- a/flyweight/flyweight_factory.py
+++ b/flyweight/flyweight_factory.py
@@ -5,13 +5,14 @@
class FlyweightFactory():
"Creating the FlyweightFactory as a singleton"
- _flyweights: dict[int, Flyweight] = {}
+ _flyweights: dict[str, Flyweight] = {} # Python 3.9
+ # _flyweights = {} # Python 3.8 or earlier
def __new__(cls):
return cls
@classmethod
- def get_flyweight(cls, code: int) -> Flyweight:
+ def get_flyweight(cls, code: str) -> Flyweight:
"A static method to get a flyweight based on a code"
if not code in cls._flyweights:
cls._flyweights[code] = Flyweight(code)
diff --git a/img/adapter_concept.svg b/img/adapter_concept.svg
index 678176e..df0bdda 100644
--- a/img/adapter_concept.svg
+++ b/img/adapter_concept.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/adapter_example.svg b/img/adapter_example.svg
index f420061..61350eb 100644
--- a/img/adapter_example.svg
+++ b/img/adapter_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/bridge_concept.svg b/img/bridge_concept.svg
index 57e6b43..b45ea91 100644
--- a/img/bridge_concept.svg
+++ b/img/bridge_concept.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/bridge_example.svg b/img/bridge_example.svg
index 5a08e19..3bd2b6c 100644
--- a/img/bridge_example.svg
+++ b/img/bridge_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/chain_of_responsibility_example.svg b/img/chain_of_responsibility_example.svg
index f95ad3b..2b62cbf 100644
--- a/img/chain_of_responsibility_example.svg
+++ b/img/chain_of_responsibility_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/command_concept.svg b/img/command_concept.svg
index 5f5613c..bd326c1 100644
--- a/img/command_concept.svg
+++ b/img/command_concept.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/command_example.svg b/img/command_example.svg
index d929490..1e14783 100644
--- a/img/command_example.svg
+++ b/img/command_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/decorator_example.svg b/img/decorator_example.svg
index 2468d17..a96e383 100644
--- a/img/decorator_example.svg
+++ b/img/decorator_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/design_patterns_in_python_book_125x178.jpg b/img/design_patterns_in_python_book_125x178.jpg
index 680a3e4..0cf8aaa 100644
Binary files a/img/design_patterns_in_python_book_125x178.jpg and b/img/design_patterns_in_python_book_125x178.jpg differ
diff --git a/img/dp_python_125.gif b/img/dp_python_125.gif
new file mode 100644
index 0000000..601a5b3
Binary files /dev/null and b/img/dp_python_125.gif differ
diff --git a/img/dp_python_250.jpg b/img/dp_python_250.jpg
new file mode 100644
index 0000000..2305ab0
Binary files /dev/null and b/img/dp_python_250.jpg differ
diff --git a/img/dp_typescript_250.jpg b/img/dp_typescript_250.jpg
new file mode 100644
index 0000000..ccb35c1
Binary files /dev/null and b/img/dp_typescript_250.jpg differ
diff --git a/img/flag_au.gif b/img/flag_au.gif
new file mode 100644
index 0000000..bcfe17a
Binary files /dev/null and b/img/flag_au.gif differ
diff --git a/img/flag_in.gif b/img/flag_in.gif
index 1a815d4..21008e1 100644
Binary files a/img/flag_in.gif and b/img/flag_in.gif differ
diff --git a/img/interpreter_example.svg b/img/interpreter_example.svg
index 10be01d..bccd8b0 100644
--- a/img/interpreter_example.svg
+++ b/img/interpreter_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/mediator_concept.svg b/img/mediator_concept.svg
index 68ddf08..050e622 100644
--- a/img/mediator_concept.svg
+++ b/img/mediator_concept.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/mediator_example.svg b/img/mediator_example.svg
index 57acae7..364b8e6 100644
--- a/img/mediator_example.svg
+++ b/img/mediator_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/observer_concept.svg b/img/observer_concept.svg
index da22d1a..5014d46 100644
--- a/img/observer_concept.svg
+++ b/img/observer_concept.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/observer_example.svg b/img/observer_example.svg
index f45e2d4..080c4f9 100644
--- a/img/observer_example.svg
+++ b/img/observer_example.svg
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/img/skillshare_btn_sm.gif b/img/skillshare_btn_sm.gif
new file mode 100644
index 0000000..aa17453
Binary files /dev/null and b/img/skillshare_btn_sm.gif differ
diff --git a/img/udemy_btn_sm.gif b/img/udemy_btn_sm.gif
new file mode 100644
index 0000000..bab7b91
Binary files /dev/null and b/img/udemy_btn_sm.gif differ
diff --git a/interpreter/README.md b/interpreter/README.md
index ecabd6d..c49e7d8 100644
--- a/interpreter/README.md
+++ b/interpreter/README.md
@@ -1,46 +1,27 @@
# Interpreter Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Interpreter Overview |
+Interpreter Use Case |
+String Slicing |
+__repr__ Dunder Method |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Interpreter** pattern helps to convert information from one language into another.
-
-The language can be anything such as words in a sentence, numerical formulas or even software code.
-
-The process is to convert the source information, into an **Abstract Syntax Tree (AST)** of **Terminal** and **Non-Terminal** expressions that all implement an `interpret()` method.
-
-A Non-Terminal expression is a combination of other Non-Terminal and/or Terminal expressions.
-
-Terminal means terminated, i.e., there is no further processing involved.
-
-An AST root starts with a Non-Terminal expression and then resolves down each branch until all expressions terminate.
-
-An example expression is `A + B` .
-
-The `A` and `B` are Terminal expressions and the `+` is Non-Terminal because it depends on the two other Terminal expressions.
-
-The Image below, is an AST for the expression `5 + 4 - 3 + 7 - 2`
-
-
-
-The official Interpreter pattern described in the original GoF Design Patterns book does not state how to construct an Abstract Syntax Tree. How your tree is constructed will depend on the grammatical constructs of your sentence that you want to interpret.
-
-Abstract Syntax Trees can be created manually or dynamically from a custom parser script. In the first example code below, I construct the AST manually.
-
-Once the AST is created, you can then choose the root node and then run the Interpret operation on that and it should interpret the whole tree recursively.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Abstract Expression**: Describe the method(s) that Terminal and Non-Terminal expressions should implement.
-* **Non-Terminal Expression**: A composite of Terminal and/or Non-Terminal expressions.
-* **Terminal Expression**: A leaf node Expression.
-* **Context**: Context is state that can be passed through interpret operations if necessary.
-* **Client**: Builds or is given an Abstract Syntax Tree to interpret.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Interpreter UML Diagram
@@ -48,20 +29,7 @@ Once the AST is created, you can then choose the root node and then run the Inte
## Source Code
-In this example, I interpret the string `5 + 4 - 3 + 7 - 2` and then calculate the result.
-
-The grammar of the string follows a pattern of Number -> Operator -> Number -> etc.
-
-I convert the string into a list of tokens that I can refer to by index in the list.
-
-I then construct the AST manually, by adding a
-
-1. Non-Terminal `Add` row containing two Terminals for the `5` and `4`,
-2. Non-Terminal `Subtract` row containing the previous Non-Terminal row and the `3`
-3. Non-Terminal `Add` row containing the previous Non-Terminal row and the `7`
-4. Non-Terminal `Subtract` row containing the previous Non-Terminal row and the `2`
-
-The AST root becomes the final row that was added, and then I can run the `interpret()` method on that, which will interpret the full AST recursively because each AST row references the row above it.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -75,9 +43,7 @@ python ./interpreter/interpreter_concept.py
## Example Use Case
-The example use case will expand on the concept example by dynamically creating the AST and converting roman numerals to integers as well as calculating the final result.
-
-The Image below, is an AST for the expression `5 + IV - 3 + VII - 2`
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._

@@ -205,10 +171,4 @@ Outputs
## Summary
-* ASTs are hard to create and are an enormous subject in themselves. My recommended approach is to create them manually first using a sample sentence to help understand all the steps individually, and then progress the conversion to be fully dynamic one step at a time ensuring that the grammatical constructs still work as you continue to progress.
-
-* The Interpreter pattern uses a class to represent each grammatical rule.
-
-* ASTs consist of multiple Non-Terminal and Terminal Expressions, that all implement an `interpret()` method.
-
-* Note that in the sample code above, the `interpret()` methods in the Non-Terminal expressions, all call further `interpret()` recursively. Only the Terminal expressions `interpret()` method returns an explicit value. See the [Number](/interpreter/number.py) class in the above code.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/interpreter/interpreter_concept.py b/interpreter/interpreter_concept.py
index bec005e..8439db5 100644
--- a/interpreter/interpreter_concept.py
+++ b/interpreter/interpreter_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"The Interpreter Pattern Concept"
@@ -7,7 +8,7 @@ class AbstractExpression():
@staticmethod
def interpret():
"""
- The `interpret` method gets called recursively for each
+ The `interpret` method gets called recursively for each
AbstractExpression
"""
@@ -65,7 +66,8 @@ def __repr__(self):
print(TOKENS)
# Manually Creating an Abstract Syntax Tree from the tokens
-AST: list[AbstractExpression] = [] # A list of AbstractExpressions
+AST: list[AbstractExpression] = [] # Python 3.9
+# AST = [] # Python 3.8 or earlier
AST.append(Add(Number(TOKENS[0]), Number(TOKENS[2]))) # 5 + 4
AST.append(Subtract(AST[0], Number(TOKENS[4]))) # ^ - 3
AST.append(Add(AST[1], Number(TOKENS[6]))) # ^ + 7
diff --git a/iterator/README.md b/iterator/README.md
index 05fc1ca..c995307 100644
--- a/iterator/README.md
+++ b/iterator/README.md
@@ -1,26 +1,26 @@
# Iterator Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Iterator Overview |
+Iterator Use Case |
+Python iter() Function |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The Iterator will commonly contain two methods that perform the following concepts.
-
-* **next**: returns the next object in the aggregate (collection, object).
-* **has_next**: returns a Boolean indicating if the Iterable is at the end of the iteration or not.
-
-The benefits of using the Iterator pattern are that the client can traverse a collection of aggregates(objects) without needing to understand their internal representations and/or data structures.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Iterator Interface**: The Interface for an object to implement.
-* **Concrete Iterator**: (Iterable) The instantiated object that implements the iterator and contains a collection of aggregates.
-* **Aggregate Interface**: An interface for defining an aggregate (object).
-* **Concrete Aggregate**: The object that implements the Aggregate interface.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Iterator UML Diagram
@@ -28,13 +28,7 @@ The benefits of using the Iterator pattern are that the client can traverse a co
## Source Code
-In this concept example, I create 4 objects called Aggregate and group them into a collection.
-
-They are very minimal objects that implement one method that prints a line.
-
-I then create an Iterable and pass in the collection of Aggregates.
-
-I can now traverse the aggregates through the Iterable interface.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -48,13 +42,7 @@ This method has been invoked
## Example Use Case
-One reason for not using the inbuilt Python data structures that implement iterators already, or using the [iter](#python-iter) function directly over an existing collection, is in the case when you want to create an object that can dynamically create iterated objects, you want a custom order of objects or an infinite iterator.
-
-The iterator in this brief example will return the next number in the iterator multiplied by 2 modulus 11. It dynamically creates the returned object (number) at runtime.
-
-It has no `has_next()` method since the result is modulated by 11, that will loop the results no matter how large the iterator index is. It will also appear to alternate between a series of even numbers and odd numbers.
-
-Also, just to demonstrate that implementing abstract classes and interfaces is not always necessary, this example uses no abstract base classes or interfaces.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -130,8 +118,4 @@ Also note that the list being printed at the end is automatically filled from th
## Summary
-* There are many ways to create Iterators. They are already built into Python and used instead of creating custom classes.
-* Use an iterator when you need to traverse over a collection, or you want an object that can output a series of dynamically created objects.
-* At minimum, an iterator needs a `next` equivalent method that returns an object.
-* Optionally you can also create a helper function that indicates whether an iterator is at the end or not. This is useful if you use your iterator in a `while` loop.
-* Alternatively, use the `sentinel` option of the Python `iter()` method to indicate the last iteration. Note that the Iterator object needs to be callable. Set the `__call__` reference to its `next` method.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/iterator/iterator_concept.py b/iterator/iterator_concept.py
index 47cb1f3..59ff128 100644
--- a/iterator/iterator_concept.py
+++ b/iterator/iterator_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"The Iterator Pattern Concept"
from abc import ABCMeta, abstractmethod
diff --git a/mediator/README.md b/mediator/README.md
index bd870e2..c62667a 100644
--- a/mediator/README.md
+++ b/mediator/README.md
@@ -1,32 +1,25 @@
# Mediator Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Mediator Overview |
+Mediator Use Case |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-Objects communicate through the **Mediator** rather than directly with each other.
-
-As a system evolves and becomes larger and supports more complex functionality and business rules, the problem of communicating between these components becomes more complicated to understand and manage. It may be beneficial to refactor your system to centralize some or all of its functionality via some kind of mediation process.
-
-The mediator pattern is similar to creating a [Facade](/facade) pattern between your classes and processes. Except the Mediator is expected to transact data both ways between two or more other classes or processes that would normally interact directly with each other.
-
-The resulting Mediator interface will be very custom to the use cases that it is now supporting.
-
-The Mediator will generally look like an object that is managing one of more [Observer](/observer) patterns perhaps between the other classes or processes (colleagues). Whether you use an Observer pattern to manage a particular piece of functionality or not depends on whether it is the best use of the resources you have available.
-
-When refactoring your code, you may decide to approach your refactoring from the perspective of implementing an Observer pattern first. This means that all colleagues (Observers) will receive the notification whether it was intended for them or not. If you want to avoid redundant updates in the colleagues then you can write specific cases in your code, or create specific methods as I have done in [/mediator/mediator_concept.py](/mediator/mediator_concept.py) file.
-
-Colleagues now will send and receive requests via a Mediator object rather than directly between each other. The Mediator is like a router in this case, but allows you to add extra programmatic functionality and also give the option of creating other kinds of colleagues that could utilize the communications in new ways.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Mediator Interface**: An interface that the Mediator and Colleagues implement. Note that different Colleagues will have varied use cases and won't need to implement all the methods described in the Mediator interface.
-* **Concrete Mediator**: The single source of truth and coordinator of communications between the components (colleagues).
-* **Colleague Classes**: One of the many types of concrete components that use the mediator for its own particular use case.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Mediator UML Diagram
@@ -34,9 +27,7 @@ Colleagues now will send and receive requests via a Mediator object rather than
## Source Code
-In the example concept, there are two colleague classes that use each other's methods. Instead of the Colleagues calling each other's methods directly, they implement the Mediator interface and call each other via the Mediator. Each colleague class or process is designed for a different purpose, but they utilize some related functionality from each other.
-
-The system would work without the Mediator, but adding the Mediator will allow extending functionality to a potential third colleague that provides a different service, such as AI analysis or monitoring, without needing to add specific support or knowledge into the two original colleagues.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -48,13 +39,7 @@ COLLEAGUE2 <--> Here is the Colleague1 specific data you asked for
## Example Use Case
-This is a simplified game engine. There is the main game engine component, a scheduler that manages game events and there are game clients that act as separate game players submitting bets into a game round.
-
-All of the components implement the Mediators interface. They all implement one or some of the methods differently depending on their purpose. While they all perform different types of functionality, they all require a single source of truth being the Game Engine that acts as the Mediator.
-
-There is mixture of this Mediator example using the [Observer](/observer) pattern to notify the game clients, as well as specific methods not necessarily shared between the scheduler, game engine and clients but benefits from being managed via the Mediator.
-
-Normally the processes being mediated will be running from different servers or programs, but in this example they are all part of the same client in order to demonstrate the concept easier.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -63,45 +48,18 @@ Normally the processes being mediated will be running from different servers or
## Output
``` bash
-python.exe ./mediator/client.py
-Sean -> New Game, Place Bets
-Cosmo -> New Game, Place Bets
-Emmy -> New Game, Place Bets
-Emmy -> You Are The Winner with result `10`. You Won 12. Your balance = 310
-```
-
-## New Coding Concepts
-
-### The Underscore Only `_` Variable
-
-In the `Player` class, there is a for loop that iterates the bets list.
-
-``` python
-for _ in bets:
- self.balance -= 1
-```
-
-The `_` is used instead of a more tradition `i`, `x`, `y` or another variable. If using a letter in the for loop, and not actually using it, like in the above example, then Pylint would indicate a warning of unused variable. Note that the Python interpreter would still run this code ok if using a letter as the variable name, but reducing Pylint warnings helps makes code look neater.
-
-E.g.,
-
-``` python
-for i in bets:
- self.balance -= 1
-```
-
-The Pylint warning would be
-
-``` bash
-W0612: Unused variable 'i' (unused-variable)
+python ./mediator/client.py
+Component1: >>> Out >>> : data A
+Component2: <<< In <<< : data A
+Component3: <<< In <<< : data A
+Component2: >>> Out >>> : data B
+Component3: <<< In <<< : data B
+Component1: <<< In <<< : data B
+Component3: >>> Out >>> : data C
+Component2: <<< In <<< : data C
+Component1: <<< In <<< : data C
```
-So, using the `_` prevents this warning.
-
## Summary
-* A mediator replaces a structure with many-to-many interactions between its classes and processes, with a one-to-many centralized structure where the interface supports all of the methods of the many-to-many structure, but via the mediator component instead.
-* The mediator pattern encourages usage of shared objects that can now be centrally managed and synchronized.
-* The mediator pattern creates an abstraction between two or more components which then makes a system easier to understand and manage.
-* The mediator pattern is similar to the [Facade](/facade) pattern, except the Mediator is expected to transact data both ways between two or more other classes or processes that would normally interact directly with each other.
-
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/mediator/client.py b/mediator/client.py
index 57c0841..2cf7662 100644
--- a/mediator/client.py
+++ b/mediator/client.py
@@ -1,40 +1,15 @@
-"Mediator Pattern Example Code"
-
-
-from game_engine import GameEngine
-from game_client import GameClient
-from player import Player
-from scheduler import Scheduler
-
-# The concrete GameEngine process that would run on a dedicated server
-GAMEENGINE = GameEngine()
-
-# 3 Hypothetical game clients, all running externally on mobile phones
-# calling the GAMEENGINE mediator across a network proxy
-MOBILECLIENT1 = GameClient(GAMEENGINE)
-PLAYER1 = Player("Sean", 100)
-MOBILECLIENT1.add_player(PLAYER1)
-
-MOBILECLIENT2 = GameClient(GAMEENGINE)
-PLAYER2 = Player("Cosmo", 200)
-MOBILECLIENT2.add_player(PLAYER2)
-
-MOBILECLIENT3 = GameClient(GAMEENGINE)
-PLAYER3 = Player("Emmy", 300, )
-MOBILECLIENT3.add_player(PLAYER3)
-
-# A scheduler is a separate process that manages game rounds and
-# triggers game events at time intervals
-SCHEDULER = Scheduler(GAMEENGINE)
-SCHEDULER.new_game()
-
-# 3 Hypothetical game clients have received notifications of new game,
-# they now place there bets
-PLAYER1.place_bets([1, 2, 3])
-PLAYER2.place_bets([5, 6, 7, 8])
-PLAYER3.place_bets([10, 11])
-
-# The scheduler closes the round, and triggers the result and
-# winnings notifications
-SCHEDULER.calculate_winners()
-SCHEDULER.notify_winners()
+"The Mediator Use Case Example"
+from component import Component
+from mediator import Mediator
+
+MEDIATOR = Mediator()
+COMPONENT1 = Component(MEDIATOR, "Component1")
+COMPONENT2 = Component(MEDIATOR, "Component2")
+COMPONENT3 = Component(MEDIATOR, "Component3")
+MEDIATOR.add(COMPONENT1)
+MEDIATOR.add(COMPONENT2)
+MEDIATOR.add(COMPONENT3)
+
+COMPONENT1.notify("data A")
+COMPONENT2.notify("data B")
+COMPONENT3.notify("data C")
diff --git a/mediator/component.py b/mediator/component.py
new file mode 100644
index 0000000..b9cf510
--- /dev/null
+++ b/mediator/component.py
@@ -0,0 +1,17 @@
+"Each component stays synchronized through a mediator"
+from interface_component import IComponent
+
+
+class Component(IComponent):
+ "Each component stays synchronized through a mediator"
+
+ def __init__(self, mediator, name):
+ self._mediator = mediator
+ self._name = name
+
+ def notify(self, message):
+ print(self._name + ": >>> Out >>> : " + message)
+ self._mediator.notify(message, self)
+
+ def receive(self, message):
+ print(self._name + ": <<< In <<< : " + message)
diff --git a/mediator/game_client.py b/mediator/game_client.py
deleted file mode 100644
index 2f2317e..0000000
--- a/mediator/game_client.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"A Game Client"
-from interface_game_engine import IGameEngine
-
-
-class GameClient(IGameEngine):
- "A Game Client that implements some of the mediator methods"
-
- def __init__(self, game_engine):
- self._alias = ""
- self._player = {}
- self._game_engine = game_engine
-
- def new_game(self):
- "not implemented in the game client"
-
- def add_player(self, player):
- self._player = player
- self._game_engine.add_player(player)
-
- def list_winners(self):
- "not implemented in the game client"
-
- def calculate_winners(self):
- "not implemented in the game client"
-
- def notify_winners(self):
- "not implemented in the game client"
-
- def game_result(self):
- "not implemented in the game client"
diff --git a/mediator/game_engine.py b/mediator/game_engine.py
deleted file mode 100644
index f7a466b..0000000
--- a/mediator/game_engine.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"A Game Engine that is the mediator"
-import random
-from interface_game_engine import IGameEngine
-
-
-class GameEngine(IGameEngine):
- "The Game Engine"
-
- def __init__(self):
- self._players = {}
- self._game_winners = {}
- self._game_result = -1
-
- def new_game(self):
- for alias in self._players:
- self._players[alias].notify(
- f"{alias} -> New Game, Place Bets")
-
- def add_player(self, player):
- self._players[player.alias] = player
-
- def list_winners(self):
- ret = []
- for key in self._players:
- ret.append([key, self._players[key].last_winnings])
- return ret
-
- def calculate_winners(self):
- self._game_result = random.randint(0, 12)
- for alias in self._players:
- player = self._players[alias]
- if self._game_result in player.bets:
- player.balance = player.balance + 12
- player.last_winnings = 12
- self._game_winners[alias] = 12
-
- def notify_winners(self):
- for alias in self._players:
- if alias in self._game_winners:
- self._players[alias].notify(
- f"{alias} -> You Are The Winner with result "
- f"`{self._game_result}`."
- f" You Won {self._players[alias].last_winnings}."
- f" Your balance = {self._players[alias].balance}"
- )
-
- def game_result(self):
- return self._game_result
diff --git a/mediator/interface_component.py b/mediator/interface_component.py
new file mode 100644
index 0000000..4592d9d
--- /dev/null
+++ b/mediator/interface_component.py
@@ -0,0 +1,16 @@
+"An interface that each component will implement"
+from abc import ABCMeta, abstractmethod
+
+
+class IComponent(metaclass=ABCMeta):
+ "An interface that each component will implement"
+
+ @staticmethod
+ @abstractmethod
+ def notify(message):
+ "The required notify method"
+
+ @staticmethod
+ @abstractmethod
+ def receive(message):
+ "The required receive method"
diff --git a/mediator/interface_game_engine.py b/mediator/interface_game_engine.py
deleted file mode 100644
index a6781af..0000000
--- a/mediator/interface_game_engine.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"The Game Client Mediator Interface"
-from abc import ABCMeta, abstractmethod
-
-
-class IGameEngine(metaclass=ABCMeta):
- "The Game Client Interface"
- @staticmethod
- @abstractmethod
- def new_game():
- "A method to implement"
-
- @staticmethod
- @abstractmethod
- def add_player(player):
- "A method to implement"
-
- @staticmethod
- @abstractmethod
- def list_winners():
- "A method to implement"
-
- @staticmethod
- @abstractmethod
- def calculate_winners():
- "A method to implement"
-
- @staticmethod
- @abstractmethod
- def notify_winners():
- "A method to implement"
-
- @staticmethod
- @abstractmethod
- def game_result():
- "A method to implement"
diff --git a/mediator/mediator.py b/mediator/mediator.py
new file mode 100644
index 0000000..4b081f0
--- /dev/null
+++ b/mediator/mediator.py
@@ -0,0 +1,18 @@
+"The Subject that all components will stay synchronized with"
+
+
+class Mediator():
+ "A Subject whose notify method is mediated"
+
+ def __init__(self):
+ self._components = set()
+
+ def add(self, component):
+ "Add components"
+ self._components.add(component)
+
+ def notify(self, message, originator):
+ "Add components except for the originator component"
+ for component in self._components:
+ if component != originator:
+ component.receive(message)
diff --git a/mediator/mediator_concept.py b/mediator/mediator_concept.py
index 161bcb8..61b52db 100644
--- a/mediator/mediator_concept.py
+++ b/mediator/mediator_concept.py
@@ -1,21 +1,8 @@
+# pylint: disable=too-few-public-methods
"Mediator Concept Sample Code"
-from abc import ABCMeta, abstractmethod
-class IMediator(metaclass=ABCMeta):
- "The Mediator interface indicating all the methods to implement"
- @staticmethod
- @abstractmethod
- def colleague1_method():
- "A method to implement"
-
- @staticmethod
- @abstractmethod
- def colleague2_method():
- "A method to implement"
-
-
-class Mediator(IMediator):
+class Mediator():
"The Mediator Concrete Class"
def __init__(self):
@@ -23,41 +10,39 @@ def __init__(self):
self.colleague2 = Colleague2()
def colleague1_method(self):
- return self.colleague1.colleague1_method()
+ "Calls the method provided by Colleague1"
+ return self.colleague1.method_1()
def colleague2_method(self):
- return self.colleague2.colleague2_method()
+ "Calls the method provided by Colleague2"
+ return self.colleague2.method_2()
-class Colleague1(IMediator):
- "This Colleague calls the other Colleague via the Mediator"
+class Colleague1():
+ "This Colleague provides data for Colleague2"
- def colleague1_method(self):
+ @staticmethod
+ def method_1():
+ "A simple method"
return "Here is the Colleague1 specific data you asked for"
- def colleague2_method(self):
- "not implemented"
-
-
-class Colleague2(IMediator):
- "This Colleague calls the other Colleague via the Mediator"
- def colleague1_method(self):
- "not implemented"
+class Colleague2():
+ "This Colleague provides data for Colleague1"
- def colleague2_method(self):
+ @staticmethod
+ def method_2():
+ "A simple method"
return "Here is the Colleague2 specific data you asked for"
-# This Client is either Colleague1 or Colleague2
-# This Colleague will instantiate a Mediator, rather than calling
-# the other Colleague directly.
+# The Client
MEDIATOR = Mediator()
-# If I am Colleague1, I want some data from Colleague2
+# Colleague1 wants some data from Colleague2
DATA = MEDIATOR.colleague2_method()
print(f"COLLEAGUE1 <--> {DATA}")
-# If I am Colleague2, I want some data from Colleague1
+# Colleague2 wants some data from Colleague1
DATA = MEDIATOR.colleague1_method()
print(f"COLLEAGUE2 <--> {DATA}")
diff --git a/mediator/player.py b/mediator/player.py
deleted file mode 100644
index 1e67e1a..0000000
--- a/mediator/player.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"A Player Object"
-
-
-class Player():
- "A Player Object"
-
- def __init__(self, alias, balance):
- self.alias = alias
- self.balance = balance
- self.bets = []
- self.last_winnings = 0
-
- def place_bets(self, bets):
- "When a player places bets, its balance is deducted"
- for _ in bets:
- self.balance -= 1
- self.bets = bets
-
- @staticmethod
- def notify(message):
- "The player is an observer of the game"
- print(message)
diff --git a/mediator/scheduler.py b/mediator/scheduler.py
deleted file mode 100644
index 70f9508..0000000
--- a/mediator/scheduler.py
+++ /dev/null
@@ -1,27 +0,0 @@
-"A Scheduler"
-from interface_game_engine import IGameEngine
-
-
-class Scheduler(IGameEngine):
- "The scheduler implements some of the Mediator methods"
-
- def __init__(self, game_engine):
- self._game_engine = game_engine
-
- def new_game(self):
- self._game_engine.new_game()
-
- def add_player(self, player):
- "not implemented in the scheduler"
-
- def list_winners(self):
- "not implemented in the scheduler"
-
- def calculate_winners(self):
- self._game_engine.calculate_winners()
-
- def notify_winners(self):
- self._game_engine.notify_winners()
-
- def game_result(self):
- "not implemented in the game client"
diff --git a/memento/README.md b/memento/README.md
index 1c5122f..98e5fe7 100644
--- a/memento/README.md
+++ b/memento/README.md
@@ -1,26 +1,26 @@
# Memento Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Memento Overview |
+Memento Use Case |
+Getters/Setters |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-Throughout the lifecycle of an application, an objects state may change. You might want to store a copy of the current state in case of later retrieval. E.g., when writing a document, you may want to auto save the current state every 10 minutes. Or you have a game, and you want to save the current position of your player in the level, with its score and current inventory.
-
-You can use the **Memento** pattern for saving a copy of state and for later retrieval if necessary.
-
-The Memento pattern, like the Command pattern, is also commonly used for implementing UNDO/REDO functionality within your application.
-
-The difference between the [Command](/command) and the Memento patterns for UNDO/REDO, is that in the Command pattern, you re-execute commands in the same order that changed attributes of a state, and with the Memento, you completely replace the state by retrieving from a cache/store.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Originator**: The originator is an object with an internal state that changes on occasion.
-* **Caretaker**: (Guardian) A Class that asks the Originator to create or restore Mementos. The Caretaker than saves them into a cache or store of mementos.
-* **Memento**: A copy of the internal state of the Originator that can later be restored back into the Originator to replace its current state.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Memento UML Diagram
@@ -28,17 +28,7 @@ The difference between the [Command](/command) and the Memento patterns for UNDO
## Source Code
-In the concept code, the client creates an object whose state will be periodically recorded. The object will be the Originator.
-
-A Caretaker is also created with a reference to the Originator.
-
-The Originators internal state is changed several times. It is then decided that the Caretaker should make a backup.
-
-More changes are made to the Originator, and then another backup is made.
-
-More changes are made to the Originator, and then it is decided that the first backup should be restored instead.
-
-And then the second backup is restored.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
### Output
@@ -63,9 +53,7 @@ State #3
## Example Use Case
-There is a game, and the character is progressing through the levels. It has acquired several new items in its inventory, the score is very good and you want to save your progress and continue later.
-
-You then decide you made a mistake and need to go back to a previous save because you took a wrong turn.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -163,12 +151,4 @@ print(example.value) # now raises an AttributeError
## Summary
-* You don't need to create a new Memento each time an Originators state changes. You can do it only when considered necessary. E.g., an occasional backup to a file.
-
-* Mementos can be stored in memory or saved/cached externally. The Caretaker will abstract the complications of storing and retrieving Mementos from the Originator.
-
-* Consider the [Command](/command) pattern for fine grained changes to an objects state to manage UNDO/REDO between memento saves. Or even save command history into a Memento that can be later replayed.
-
-* In my examples, the whole state is recorded and changed with the Memento. You can use the Memento to record and change partial states instead if required.
-
-* When copying state, be aware of shallow/deep copying. In complicated projects, your restore functionality will probably contain a combination of both the [Command](/command) and Memento patterns.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/observer/README.md b/observer/README.md
index 20232e7..1965ab3 100644
--- a/observer/README.md
+++ b/observer/README.md
@@ -1,49 +1,26 @@
# Observer Pattern
+## Videos
+
+Section | Video Links
+-|-
+Observer Overview |
+Observer Use Case |
+Python **Set** |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Observer** pattern is a software design pattern in which an object, called the **Subject** (**Observable**), manages a list of dependents, called **Observers**, and notifies them automatically of any internal state changes by calling one of their methods.
-
-The Observer pattern follows the publish/subscribe concept. A subscriber, subscribes to a publisher. The publisher then notifies the subscribers when necessary.
-
-The observer stores state that should be consistent with the subject. The observer only needs to store what is necessary for its own purposes.
-
-A typical place to use the observer pattern is between your application and presentation layers. Your application is the manager of the data and is the single source of truth, and when the data changes, it can update all of the subscribers, that could be part of multiple presentation layers. For example, the score was changed in a televised cricket game, so all the web browser clients, mobile phone applications, leaderboard display on the ground and television graphics overlay, can all now have the updated information synchronized.
-
-Most applications that involve a separation of data into a presentation layer can be broken further down into the Model-View-Controller (MVC) concept.
-
-* **Controller** : The single source of truth.
-* **Model** : The link or relay between a controller and a view. It may use any of the structural patterns (adapter, bridge, facade, proxy, etc.) at some point.
-* **View** : The presentation layer of the of the data from the model.
-
-The observer pattern can be used to manage the transfer of data across any layer and even internally to itself to add a further abstraction. In the MVC structure, the View can be a subscriber to the Model, that in turn can also be a subscriber to the controller. It can also happen the other way around if the use case warrants.
-
-The Observer pattern allows you to vary subjects and observers independently. You can reuse subjects without reusing their observers, and vice versa. It lets you add observers without modifying the subject or any of the other observers.
-
-The observer pattern is commonly described as a push model, where the subject pushes updates to all observers. But observers can pull for updates and also only if it decides it is necessary.
-
-Whether you decide to use a push or pull concept to move data, then there are pros and cons to each. You may decide to use a combination of both to manage reliability.
-
-E.g., When sending messages across a network, the receiving client, can be slow to receive the full message that was sent, or even timeout. This pushing from the sender's side can increase the amount of network hooks or threads if there are many messages still waiting to be fully delivered. The subject is taking responsibility for the delivery.
-
-On the other hand, if the observer requests for an update from the subscriber, then the subject (observable) can return the information as part of the requests response. The observer could also indicate as part of the request, to only return data applicable to X, which would then make the response message smaller to transfer at the expense of making the observable more coupled to the observer.
-
-Use a push mechanism from the subject when updates are absolutely required in as close to real time from the perspective of the observer, noting that you may need to manage the potential of extra unresolved resources queueing up at the sender.
-
-If updates on the observer end are allowed to suffer from some delay, then a pull mechanism is most reliable and easiest to manage since it is the responsibly of the observer to synchronize its state.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Subject Interface**: (Observable Interface) The interface that the subject should implement.
-* **Concrete Subject**: (Observable) The object that is the subject.
-* **Observer Interface**: The interface that the observer should implement.
-* **Concrete Observer**: The object that is the observer. There can be a variable number of observers which can subscribe/unsubscribe during runtime.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Observer UML Diagram
@@ -51,15 +28,7 @@ If updates on the observer end are allowed to suffer from some delay, then a pul
## Source Code
-A Subject (Observable) is created.
-
-Two Observers are created. They could be across a network, but for demonstration purposes are within the same client.
-
-The Subject notifies the Observers.
-
-One of the Observers unsubscribes,
-
-The Subject notifies the remaining Observer again.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -72,21 +41,7 @@ Observer id:2084220160272 received ('Second Notification', {'A': 1, 'B': 2, 'C':
## Example Use Case
-This example mimics the **MVC** approach described earlier.
-
-There is an external process called a `DataController`, and a client process that holds a `DataModel` and multiple `DataViews` which are a Pie graph, Bar graph and Table view.
-
-Note that this example runs in a single process, but imagine that the `DataController` is actually an external process running on a different server.
-
-The `DataModel` subscribes to the `DataController` and the `DataViews` subscribe to the `DataModel` .
-
-The client sets up the various views with a subscription to the `DataModel` .
-
-The hypothetical external `DataController` then updates the external data, and the data then propagates through the layers to the views.
-
-Note that in reality this example would be much more complex if multiple servers are involved. I am keeping it brief to demonstrate one possible use case of the observer pattern.
-
-Also note that in the `DataController`, the references to the observers are contained in a [Set](#python-set), while in the `DataModel` I have used a [Dictionary](/singleton#python-dictionary) instead, so that you can see an alternate approach.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -129,13 +84,8 @@ PS> python
{'grandy', 'yankee', 'dandy'}
```
-!!! Note
-
- If instantiating an empty **Set** then use `my_object = Set()` rather than `my_object = {}` to reduce ambiguity with creating an empty [Dictionary](/singleton#python-dictionary).
+Note, if instantiating an empty **Set** then use `my_object = Set()` rather than `my_object = {}` to reduce ambiguity with creating an empty [Dictionary](/singleton#python-dictionary).
## Summary
-* Use when a change to one object requires changing others and you don't know how many other objects need to be changed.
-* A subject has a list of observers, each conforming to the observer interface. The subject doesn't need to know about the concrete class of any observer. It will notify the observer using the method described in the interface.
-* Subjects and Observers can belong to any layer of a system whether extremely large or small.
-* Using a Push or Pull mechanism for the Observer will depend on how you want your system to manage redundancy for particular data transfers. These things become more of a consideration when the Observer is separated further away from a subject and the message needs to traverse many layers, processes and systems.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/observer/observer_concept.py b/observer/observer_concept.py
index 950a4f1..1c29aa3 100644
--- a/observer/observer_concept.py
+++ b/observer/observer_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"Observer Design Pattern Concept"
from abc import ABCMeta, abstractmethod
@@ -37,7 +38,7 @@ def unsubscribe(self, observer):
def notify(self, *args):
for observer in self._observers:
- observer.notify(self, *args)
+ observer.notify(*args)
class IObserver(metaclass=ABCMeta):
@@ -55,7 +56,7 @@ class Observer(IObserver):
def __init__(self, observable):
observable.subscribe(self)
- def notify(self, observable, *args):
+ def notify(self, *args):
print(f"Observer id:{id(self)} received {args}")
diff --git a/prototype/README.md b/prototype/README.md
index 5d395ab..0b69ff8 100644
--- a/prototype/README.md
+++ b/prototype/README.md
@@ -2,38 +2,25 @@
## Videos
-Section | Video Link
+Section | Video Links
-|-
-Overview |
-Example Use Case |
-id() function |
+Prototype Overview |
+Prototype Use Case |
+Python **id()** function |
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Prototype** design pattern is good for when creating new objects requires more resources than you want to use or have available. You can save resources by just creating a copy of any existing object that is already in memory.
-
-E.g., A file you've downloaded from a server may be large, but since it is already in memory, you could just clone it, and work on the new copy independently of the original.
-
-In the Prototype patterns interface, you create a static clone method that should be implemented by all classes that use the interface.
-How the clone method is implemented in the concrete class is up to you.
-You will need to decide whether a shallow or deep copy is required.
-
-* A shallow copy, copies and creates new references one level deep,
-* A deep copy, copies and creates new references for all levels.
-
-In Python you have mutable objects such as [Lists](/builder#python-list), [Dictionaries](/singleton#python-dictionary), [Sets](/observer#python-set) and any custom Objects you may have created. A shallow copy, will create new copies of the objects with new references in memory, but the underlying sub data, e.g., the elements in a list, will point to the same memory location as the original object being copied. You will now have two lists, but the elements within the lists will point to the same memory location. So, changing any elements of a copied list will affect the original list also. Be sure to test your implementation that the copy method you use works as expected. Shallow copies are much faster to process than deep copies and deep copies are not always necessary if you are not going to benefit from using it.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Prototype Interface**: The interface that describes the `clone()` method.
-* **Prototype**: The Object/Product that implements the Prototype interface.
-* **Client**: The client application that uses and creates the ProtoType.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Prototype UML Diagram
@@ -41,14 +28,8 @@ In Python you have mutable objects such as [Lists](/builder#python-list), [Dicti
## Source Code
-Experiment with the concept code.
-
-By default, it will shallow copy the object you've asked to be cloned. The object can be any type from number to string to dictionary to anything custom that you've created.
-
-In my example, I have created a list of numbers. At first impressions, when this list is copied, it will appear that the list was fully cloned. But the inner items of the list were not. They will point to the same memory location as the original list; however, the memory identifier of the new list is new and different from the original.
-
-In the `MyClass.clone()` method, there is a line `self.field.copy()` that is commented out. Uncomment out this line, and comment out the line before it to now be `# self.field` . Re execute the file, and now the list items will be copied as well. This however is still not a full deep copy. If the list items were actually other lists, dictionaries or other collections, rather than the numbers that they are, then only the 1st level of that copy would have been cloned to new memory identifiers. I call this a 2-level copy.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
-For a full recursive copy, use the `copy.deepcopy()` method that is part of an extra dedicated `copy` import included with Python. I demonstrate this in the [/prototype/document.py](/prototype/document.py) file.
+## Summary
-Remember that full deep copies can potentially be much slower for very complicated object hierarchies.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/prototype/prototype_concept.py b/prototype/prototype_concept.py
index a1c0ef8..3c82b1b 100644
--- a/prototype/prototype_concept.py
+++ b/prototype/prototype_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"Prototype Concept Sample Code"
from abc import ABCMeta, abstractmethod
diff --git a/proxy/README.md b/proxy/README.md
index cb43743..64456cf 100644
--- a/proxy/README.md
+++ b/proxy/README.md
@@ -1,39 +1,27 @@
# Proxy Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Proxy Overview |
+Proxy Use Case |
+**\_\_class\_\_** Attribute |
+Circular Imports |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Proxy** design pattern is a class functioning as an interface to another class or object.
-
-A Proxy could be for anything, such as a network connection, an object in memory, a file, or anything else you need to provide an abstraction between.
-
-Types of proxies,
-
-* **Virtual Proxy**: An object that can cache parts of the real object, and then complete loading the full object when necessary.
-
-* **Remote Proxy**: Can relay messages to a real object that exists in a different address space.
-
-* **Protection Proxy**: Apply an authentication layer in front of the real object.
-
-* **Smart Reference**: An object which whose internal attributes can be overridden or replaced.
-
-Additional functionality can be provided at the proxy abstraction if required. E.g., caching, authorization, validation, lazy initialization, logging.
-
-The proxy should implement the subject interface as much as practicable so that the proxy and subject appear identical to the client.
-
-The Proxy Pattern can also be called **Monkey Patching** or **Object Augmentation**
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Proxy**: An object with an interface identical to the real subject. Can act as a placeholder until the real subject is loaded or as gatekeeper applying extra functionality.
-* **Subject Interface**: An interface implemented by both the Proxy and Real Subject.
-* **Real Subject**: The actual real object that the proxy is representing.
-* **Client**: The client application that uses and creates the Proxy.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Proxy UML Diagram
@@ -52,11 +40,7 @@ pulling data from Proxy cache
## Example Use Case
-In this example, I dynamically change the class of an object. So, I am essentially using an object as a proxy to other classes.
-
-Every time the `tell_me_the_future()` method is called; it will randomly change the object to use a different class.
-
-The object `PROTEUS` will then use the same static attributes and class methods of the new class instead.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -117,11 +101,4 @@ See the [Lion](/proxy/lion.py), [Serpent](/proxy/serpent.py) and [Leopard](/prox
## Summary
-* Proxy forwards requests onto the Real Subject when applicable, depending on the kind of proxy.
-* A virtual proxy can cache elements of a real subject before loading the full object into memory.
-* A protection proxy can provide an authentication layer. For example, an NGINX proxy can add Basic Authentication restriction to a HTTP request.
-* A proxy can perform multiple tasks if necessary.
-* A proxy is different than an [Adapter](/adapter). The Adapter will try to adapt two existing interfaces together. The Proxy will use the same interface as the subject.
-* It is also very similar to the [Facade](/facade), except you can add extra responsibilities, just like the [Decorator](/decorator). The Decorator however can be used recursively.
-* The intent of the Proxy is to provide a stand in for when it is inconvenient to access a real subject directly.
-* The Proxy design pattern may also be called the Surrogate design pattern.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/proxy/proxy_concept.py b/proxy/proxy_concept.py
index e7ff9ff..bdbe2f9 100644
--- a/proxy/proxy_concept.py
+++ b/proxy/proxy_concept.py
@@ -1,8 +1,10 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"A Proxy Concept Example"
from abc import ABCMeta, abstractmethod
+
class ISubject(metaclass=ABCMeta):
"An interface implemented by both the Proxy and Real Subject"
@staticmethod
@@ -10,6 +12,7 @@ class ISubject(metaclass=ABCMeta):
def request():
"A method to implement"
+
class RealSubject(ISubject):
"The actual real object that the proxy is representing"
@@ -20,6 +23,7 @@ def __init__(self):
def request(self):
return self.enormous_data
+
class Proxy(ISubject):
"""
The proxy. In this case the proxy will act as a cache for
@@ -36,13 +40,14 @@ def request(self):
Using the proxy as a cache, and loading data into it only if
it is needed
"""
- if self.enormous_data == []:
+ if not self.enormous_data:
print("pulling data from RealSubject")
self.enormous_data = self.real_subject.request()
return self.enormous_data
print("pulling data from Proxy cache")
return self.enormous_data
+
# The Client
SUBJECT = Proxy()
# use SUBJECT
@@ -50,4 +55,4 @@ def request(self):
# load the enormous amounts of data because now we want to show it.
print(SUBJECT.request())
# show the data again, but this time it retrieves it from the local cache
-print(SUBJECT.request())
\ No newline at end of file
+print(SUBJECT.request())
diff --git a/singleton/README.md b/singleton/README.md
index cd1dab2..c2cebd3 100644
--- a/singleton/README.md
+++ b/singleton/README.md
@@ -2,29 +2,21 @@
## Videos
-Section | Video Link
+Section | Video Links
-|-
-Overview |
-Example Use Case |
-Dictionary |
+Singleton Overview |
+Singleton Use Case |
+Python **Dictionary** |
## Book
Cover | Links |
-|-|
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J|
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC|
## Overview
-Sometimes you need an object in an application where there is only one instance.
-
-You don't want there to be many versions, for example, you have a game with a score and you want to adjust it. You may have accidentally created several instances of the class holding the score object. Or, you may be opening a database connection, there is no need to create many, when you can use the existing one that is already in memory. You may want a logging component, and you want to ensure all classes use the same instance. So, every class could declare their own logger component, but behind the scenes, they all point to the same memory address (id).
-
-By creating a class using the **Singleton** pattern, you can enforce that even if a second instance was created, it will still refer to the original.
-
-The Singleton can be accessible globally, but it is not a global variable. It is a class that can be instanced at any time, but after it is first instanced, any new instances will point to the same instance as the first.
-
-For a class to behave as a Singleton, it should not contain any references to `self` but use static variables, static methods and/or class methods.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Singleton UML Diagram
@@ -40,27 +32,11 @@ id(OBJECT2) = 2164775087968
id(OBJECT3) = 2164775087968
```
-Variables declared at class level are static variables that can be accessed directly using the class name without the class needing to be instantiated first.
-
-**cls** is a reference to the class
-
-**self** is a reference to the instance of the class
-
-**\__new\__** gets called before **\__init\__**
-
-**\__new\__** has access to class level variables
-
-**\__init\__** references self which is created when the class is instantiated
-
-By using **\__new\__**, and returning a reference to **cls**, we can force the class to act as a singleton. For a class to act as a singleton, it should not contain any references to **self**.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example Use Case
-In the example, there are three games created. They are all independent instances created from their own class, but they all share the same leaderboard. The leaderboard is a singleton.
-
-It doesn't matter how the Games where created, or how they reference the leaderboard, it is always a singleton.
-
-Each game independently adds a winner, and all games can read the altered leaderboard regardless of which game updated it.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Example UML Diagram
@@ -157,8 +133,4 @@ PS> python
## Summary
-* To be a Singleton, there must only be one copy of the Singleton, no matter how many times, or in which class it was instantiated.
-* You want the attributes or methods to be globally accessible across your application, so that other classes may be able to use the Singleton.
-* You can use Singletons in other classes, as I did with the leaderboard, and they will all use the same Singleton regardless.
-* You want controlled access to a sole instance.
-* For a class to act as a singleton, it should not contain any references to `self`.
\ No newline at end of file
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/singleton/singleton_concept.py b/singleton/singleton_concept.py
index 0942a30..1d9d869 100644
--- a/singleton/singleton_concept.py
+++ b/singleton/singleton_concept.py
@@ -2,6 +2,7 @@
"Singleton Concept Sample Code"
import copy
+
class Singleton():
"The Singleton Class"
value = []
@@ -21,6 +22,7 @@ def class_method(cls):
"Use @classmethod to access class level variables"
print(cls.value)
+
# The Client
# All uses of singleton point to the same memory address (id)
print(f"id(Singleton)\t= {id(Singleton)}")
@@ -32,4 +34,4 @@ def class_method(cls):
print(f"id(OBJECT2)\t= {id(OBJECT2)}")
OBJECT3 = Singleton()
-print(f"id(OBJECT1)\t= {id(OBJECT3)}")
\ No newline at end of file
+print(f"id(OBJECT1)\t= {id(OBJECT3)}")
diff --git a/state/README.md b/state/README.md
index 1f5a513..4f1fce5 100644
--- a/state/README.md
+++ b/state/README.md
@@ -1,24 +1,26 @@
# State Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+State Overview |
+State Use Case |
+**\_\_call\_\_** Attribute |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-Not to be confused with object state, i.e., one of more attributes that can be copied as a snapshot, the **State Pattern** is more concerned about changing the handle of an object's method dynamically. This makes an object itself more dynamic and may reduce the need of many conditional statements.
-
-Instead of storing a value in an attribute, and then then using conditional statements within an objects method to produce different output, a subclass is assigned as a handle instead. The object/context doesn't need to know about the inner working of the assigned subclass that the task was delegated to.
-
-In the state pattern, the behavior of an objects state is encapsulated within the subclasses that are dynamically assigned to handle it.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **State Interface**: An interface for encapsulating the behavior associated with a particular state of the Context.
-* **Concrete Subclasses**: Each subclass implements a behavior associated with the particular state.
-* **Context**: This is the object where the state is defined, but the execution of the state behavior is redirected to the concrete subclass.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## State UML Diagram
@@ -26,7 +28,7 @@ In the state pattern, the behavior of an objects state is encapsulated within th
## Source Code
-In the concept example, there are three possible states. Every time the `request()` method is called, the concrete state subclass is randomly selected by the context.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
### Output
@@ -41,9 +43,7 @@ I am ConcreteStateC
## State Example Use Case
-This example takes the concept example further and uses an iterator rather than choosing the states subclasses randomly.
-
-When the iterator gets to the end, it raises a `StopIteration` error and recreates the iterator so that the process can loop again.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## State Example Use Case UML Diagram
@@ -92,6 +92,4 @@ EXAMPLE() # function now gets called by default
## Summary
-* Makes an object change its behavior when its internal state changes.
-* The client and the context are not concerned about the details of how the state is created/assembled/calculated. The client will call a method of the context and it will be handled by a subclass.
-* The State pattern appears very similar to the [Strategy](/strategy) pattern, except in the State pattern, the object/context has changed to a different state and will run a different subclass depending on that state.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/strategy/README.md b/strategy/README.md
index 21b2978..8f1a389 100644
--- a/strategy/README.md
+++ b/strategy/README.md
@@ -1,36 +1,25 @@
# Strategy Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Strategy Overview |
+Strategy Use Case |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-The **Strategy** Pattern is similar to the [State](/state) Pattern, except that the client passes in the algorithm that the context should run and the execution of the algorithm does not affect the state of the context.
-
-The algorithm should be contained within a class that implements the particular strategies interface.
-
-An application that sorts data is a good example of where you can incorporate the Strategy pattern.
-
-There are many methods of sorting a set of data. E.g., Quicksort, Mergesort, Introsort, Heapsort, Bubblesort. See [https://en.wikipedia.org/wiki/Sorting_algorithm](https://en.wikipedia.org/wiki/Sorting_algorithm) for more examples.
-
-The user interface of the client application can provide a drop-down menu to allow the user to try the different sorting algorithms.
-
-Upon user selection, a reference to the algorithm will be passed to the context and processed using this new algorithm instead.
-
-The Strategy and [State](/state) appear very similar, a good way to differentiate them is to consider whether the context is considered to be in a new state or not at various times in the lifecycle.
-
-In the Strategy, an object/context runs a chosen algorithm, but the state of the object/context doesn't change in case you want to try a different algorithm.
-
-Software Plugins can be implemented using the Strategy pattern.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Strategy Interface**: An interface that all Strategy subclasses/algorithms must implement.
-* **Concrete Strategy**: The subclass that implements an alternative algorithm.
-* **Context**: This is the object that receives the concrete strategy in order to execute it.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Strategy UML Diagram
@@ -38,14 +27,12 @@ Software Plugins can be implemented using the Strategy pattern.
## Source Code
-There is a Context, and three different strategies to choose from.
-
-Each Strategy is executed in turn by the context.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
``` bash
-python.exe ./strategy/strategy_concept.py
+python ./strategy/strategy_concept.py
I am ConcreteStrategyA
I am ConcreteStrategyB
I am ConcreteStrategyC
@@ -53,9 +40,7 @@ I am ConcreteStrategyC
## Strategy Example Use Case
-A game character is moving through an environment. Depending on the situation within the current environment, the user decides to use a different movement algorithm. From the perspective of the object/context, it is still a move, but the implementation is encapsulated in the subclass at the handle.
-
-In a real game, the types of things that a particular move could affect is which animation is looped, whether physics attributes changed, the speed of movement, the camera follow mode and more.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Strategy Example Use Case UML Diagram
@@ -64,18 +49,12 @@ In a real game, the types of things that a particular move could affect is which
## Output
``` bash
-python.exe ./strategy/client.py
-I am Walking
-I am Running
-I am Crawling
+python ./strategy/client.py
+I am Walking. New position = [1, 0]
+I am Running. New position = [3, 0]
+I am Crawling. New position = [3.5, 0]
```
## Summary
-* While the Strategy pattern looks very similar to the State pattern, the assigned strategy sub class/algorithm is not changing any state of the context. The class/algorithm can be re-executed or replaced with a different class/algorithm with no effect to the state of the context.
-
-* The Strategy pattern is about having a choice of implementations that accomplish the same relative task.
-
-* The particular strategies algorithm is encapsulated in order to keep the implementation of it de coupled from the context.
-
-* As soon as the state of the context decides which subclass will be executed, then that is the State pattern, otherwise it is the Strategy pattern because the decision was made externally to the context and can be modified again without affecting the context.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/strategy/client.py b/strategy/client.py
index d84e559..33eca01 100644
--- a/strategy/client.py
+++ b/strategy/client.py
@@ -6,10 +6,12 @@
class GameCharacter():
"This is the context whose strategy will change"
- @staticmethod
- def move(movement_style):
+ position = [0, 0]
+
+ @classmethod
+ def move(cls, movement_style):
"The movement algorithm has been decided by the client"
- movement_style()
+ movement_style(cls.position)
class IMove(metaclass=ABCMeta):
@@ -25,9 +27,10 @@ class Walking(IMove):
"A Concrete Strategy Subclass"
@staticmethod
- def walk():
+ def walk(position):
"A walk algorithm"
- print("I am Walking")
+ position[0] += 1
+ print(f"I am Walking. New position = {position}")
__call__ = walk
@@ -36,9 +39,10 @@ class Running(IMove):
"A Concrete Strategy Subclass"
@staticmethod
- def run():
+ def run(position):
"A run algorithm"
- print("I am Running")
+ position[0] += 2
+ print(f"I am Running. New position = {position}")
__call__ = run
@@ -47,9 +51,10 @@ class Crawling(IMove):
"A Concrete Strategy Subclass"
@staticmethod
- def crawl():
+ def crawl(position):
"A crawl algorithm"
- print("I am Crawling")
+ position[0] += 0.5
+ print(f"I am Crawling. New position = {position}")
__call__ = crawl
diff --git a/template/README.md b/template/README.md
index 6033477..fe00545 100644
--- a/template/README.md
+++ b/template/README.md
@@ -1,33 +1,25 @@
# Template Method Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Template Method Overview |
+Template Method Use Case |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-In the **Template Method** pattern, you create an abstract class (template) that contains a **Template Method** which is a series of instructions which are a combination of abstract and hook methods.
-
-Abstract methods need to be overridden in the subclasses that extend the abstract (template) class.
-
-Hook methods normally have empty bodies in the abstract class. Subclasses can optionally override the hook methods to create custom implementations.
-
-So, what you have, is an abstract class, with several types of methods, being the main template method, and a combination of abstract and/or hooks, that can be extended by different subclasses which all have the option of customizing the behavior of the template class without changing its underlying algorithm structure.
-
-Template methods are useful to help you factor out common behavior within your library classes.
-
-Note that this pattern describes the behavior of a **method** and how its inner method calls behave.
-
-Hooks are default behavior and can be overridden. They are normally empty by default.
-
-Abstract methods, must be overridden in the concrete class that extends the template class.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Abstract Class**: Defines the template method and the primitive steps as abstract and/or hook methods.
-* **Concrete Class**: A subclass that extends some or all of the abstract class primitive methods.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Template Method UML Diagram
@@ -35,9 +27,7 @@ Abstract methods, must be overridden in the concrete class that extends the temp
## Source Code
-Note that in both the concrete classes in this concept example, the `template_method()` was not overridden since it was already inherited. Only the primitives (abstract or hooks) were optionally overridden.
-
-To create an empty abstract method in your abstract class, that must be overridden in a subclass, then use the ABCMeta `@abstractmethod` decorator.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -52,11 +42,7 @@ Class_B : Step Three. (overridden)
## Template Method Example Use Case
-In the example use case, there is an `AbstractDocument` with several methods, some are optional and others must be overridden.
-
-The document will be written out in two different formats.
-
-Depending on the concrete class used, the `text()` method will wrap new lines with `
` tags and the `print()` method will format text with tabs, or include html tags.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Template Method Use Case UML Diagram
@@ -90,10 +76,4 @@ footer : -- Page 1 --
## Summary
-* The Template method defines an algorithm in terms of abstract operations and subclasses override some or all of the methods to create concrete behaviors.
-
-* Abstract methods must be overridden in the subclasses that extend the abstract class.
-
-* Hook Methods usually have empty bodies in the superclass but can be optionally overridden in the subclass.
-
-* If a class contains many conditional statements, consider converting it to use the Template Method pattern.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/visitor/README.md b/visitor/README.md
index 054c44a..1f969de 100644
--- a/visitor/README.md
+++ b/visitor/README.md
@@ -1,31 +1,27 @@
# Visitor Design Pattern
+## Videos
+
+Section | Video Links
+-|-
+Visitor Overview |
+Visitor Use Case |
+hasattr() Method |
+expandtabs() Method |
+
## Book
Cover | Links
-|-
- |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
+ |
https://www.amazon.com/dp/B08XLJ8Z2J
https://www.amazon.co.uk/dp/B08XLJ8Z2J
https://www.amazon.in/dp/B08Z282SBC
https://www.amazon.de/dp/B08XLJ8Z2J
https://www.amazon.fr/dp/B08XLJ8Z2J
https://www.amazon.es/dp/B08XLJ8Z2J
https://www.amazon.it/dp/B08XLJ8Z2J
https://www.amazon.co.jp/dp/B08XLJ8Z2J
https://www.amazon.ca/dp/B08XLJ8Z2J
https://www.amazon.com.au/dp/B08Z282SBC
## Overview
-Your object structure inside an application may be complicated and varied. A good example is what could be created using the [Composite](/composite) structure.
-
-The objects that make up the hierarchy of objects, can be anything and most likely complicated to modify as your application grows.
-
-Instead, when designing the objects in your application that may be structured in a hierarchical fashion, you can allow them to implement a **Visitor** interface.
-
-The Visitor interface describes an `accept()` method that a different object, called a Visitor, will use in order to traverse through the existing object hierarchy and read the internal attributes of an object.
-
-The Visitor pattern is useful when you want to analyze, or reproduce an alternative object hierarchy without implementing extra code in the object classes, except for the original requirements set by implementing the Visitor interface.
-
-Similar to the template pattern it could be used to output different versions of a document but more suited to objects that may be members of a hierarchy.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Terminology
-* **Visitor Interface**: An interface for the Concrete Visitors.
-* **Concrete Visitor**: The Concrete Visitor will traverse the hierarchy of elements.
-* **Visitable Interface**: The interface that elements should implement which describes the `accept()` method that will allow them to be visited (traversed).
-* **Concrete Element**: An object that will be visited. An application will contain a variable number of Elements than can be structured in any particular hierarchy.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Visitor UML Diagram
@@ -33,13 +29,7 @@ Similar to the template pattern it could be used to output different versions of
## Source Code
-In the concept code below, a hierarchy of any object is created. It is similar to a simplified composite. The objects of `Element` can also contain a hierarchy of sub elements.
-
-The `Element` class could also consist of many variations, but this example uses only one.
-
-Rather than writing specific code inside all these elements every time I wanted to handle a new custom operation, I can implement the `IVisitable` interface and create the `accept()` method which allows the Visitor to pass through it and access the Elements internal attributes.
-
-Two different Visitor classes are created, `PrintElementNamesVisitor` and `CalculateElementTotalsVisitor` . They are instantiated and passed through the existing Object hierarchy using the same `IVisitable` interface.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Output
@@ -54,13 +44,7 @@ A
## Visitor Example Use Case
-In the example, the client creates a car with parts.
-
-The car and parts inherit an abstract car parts class with predefined property getters and setters.
-
-Instead of creating methods in the car parts classes and abstract class that run bespoke methods, the car parts can all implement the `IVisitor` interface.
-
-This allows for the later creation of Visitor objects to run specific tasks on the existing hierarchy of objects.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
## Visitor Example UML Diagram
@@ -157,7 +141,4 @@ jklmn 1011
## Summary
-* Use the Visitor pattern to define an operation to be performed on the elements of a hierarchal object structure.
-* Use the Visitor pattern to define the new operation without needing to change the classes of the elements on which it operates.
-* When designing your application, you can provision for the future possibility of needing to run custom operations on an element hierarchy, by implementing the Visitor interface in anticipation.
-* Usage of the Visitor pattern helps to ensure that your classes conform to the single responsibility principle due to them implementing the custom visitor behavior in a separate class.
+_... Refer to [Book](https://amzn.to/466lBN6) or [Design Patterns In Python website](https://sbcode.net/python/) to read textual content._
\ No newline at end of file
diff --git a/visitor/client.py b/visitor/client.py
index 2c43a76..293cd4a 100644
--- a/visitor/client.py
+++ b/visitor/client.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"The Visitor Pattern Use Case Example"
from abc import ABCMeta, abstractmethod
@@ -59,9 +60,9 @@ class Body(AbstractCarPart, IVisitable):
"A part of the car"
def __init__(self, name, sku, price):
- self._name = name
- self._sku = sku
- self._price = price
+ self.name = name
+ self.sku = sku
+ self.price = price
def accept(self, visitor):
visitor.visit(self)
@@ -71,9 +72,9 @@ class Engine(AbstractCarPart, IVisitable):
"A part of the car"
def __init__(self, name, sku, price):
- self._name = name
- self._sku = sku
- self._price = price
+ self.name = name
+ self.sku = sku
+ self.price = price
def accept(self, visitor):
visitor.visit(self)
@@ -83,9 +84,9 @@ class Wheel(AbstractCarPart, IVisitable):
"A part of the car"
def __init__(self, name, sku, price):
- self._name = name
- self._sku = sku
- self._price = price
+ self.name = name
+ self.sku = sku
+ self.price = price
def accept(self, visitor):
visitor.visit(self)
@@ -95,7 +96,7 @@ class Car(AbstractCarPart, IVisitable):
"A Car with parts"
def __init__(self, name):
- self._name = name
+ self.name = name
self._parts = [
Body("Utility", "ABC-123-21", 1001),
Engine("V8 engine", "DEF-456-21", 2555),
diff --git a/visitor/visitor_concept.py b/visitor/visitor_concept.py
index 2fdf969..f3c33fb 100644
--- a/visitor/visitor_concept.py
+++ b/visitor/visitor_concept.py
@@ -1,4 +1,5 @@
# pylint: disable=too-few-public-methods
+# pylint: disable=arguments-differ
"The Visitor Pattern Concept"
from abc import ABCMeta, abstractmethod