- This repository contains an overview of the Gang of Four (GoF) design patterns with modern-day variations, adjustments, and discussions in Python.
 
- SOLID Design Principles:
 - Creational Design Patterns: 
- Builder 
- A builder is a separate component for building an object
 - Can either give builder an initializer or return it via a static function
 - To make builder fluent, return self
 - Different facets of an object can be built with different builders working in tandem via a base class
 
 - Factories (Factory Method and Abstract Factory) 
- A factory method is a static method that creates object
 - A factory is an entity that can take care of object creation
 - A factory can be external or reside inside the object as an inner class
 - Hierarchies of factories can be used to create related objects
 
 - Prototype 
- To implement a prototype, partially construct an object and store it somewhere
 - Deep copy the prototype
 - Customize the resulting instance
 - A factory provides a convenient API for using prototypes
 
 - Singleton 
- Different realizations of Singleton: custom allocator, decorator, metaclass
 - Laziness is easy, just init on first request
 - Monostate variation
 - Testability issues
 
 
 - Builder 
 - Structural Design Patterns: 
- Adapter 
- Implementing an Adapter is easy
 - Determine the API you have and the API you need
 - Create a component which aggregates (has a reference to, ...) the adaptee
 - Intermediate representations can pile up: use caching and other optimizations
 
 - Bridge 
- Decouple abstraction from implementation
 - Both can exist as hierarchies
 - A stronger form of encapsulation
 
 - Composite 
- Objects can use other objects via inheritance/composition
 - Some composed and singular objects need similar/identical behaviors
 - Composite design pattern lets us treat both types of objects uniformly
 - Python supports iteration with __iter__ and Iterable ABC
 - A single object can itself iterable by yielding self from __iter__
 
 - Decorator 
- A decorator keeps the reference to the decorated object(s)
 - Adds utility attributes and methods to augment the object's features
 - May or may not forward calls to the underlying object
 - Proxying of underlying calls can be done dynamically
 - Python's functional decorators wrap functions; no direct relation to the GoF Decorator Pattern
 
 - Façade 
- Build a Facade to provide a simplified API over a set of classes
 - May wish to (optionally) expose internals through the facade
 - May allow users to 'escalate' to use more complex API
 
 - Flyweight 
- Store common data externally
 - Specify an index or a reference into the external data store
 - Define the idea of 'ranges' on homogeneuous collections and store data related to those ranges
 
 - Proxy 
- A proxy has the same interface as underlying object
 - To create a proxy, simple replicate the existing interface of an object
 - Add relevant functionality to the redefined member functions
 - Different proxies (communications, logging, caching, etc.) have completely different behaviors
 
 
 - Adapter 
 - Behavioral Design Patterns 
- Chain of Responsibility 
- Chain of responsibility can be implemented as a chain of references or a centralized construct
 - Enlist objects in the chain, possibly controlling their order
 - Object removal from chain (e.g., __exit__)
 
 - Command 
- Encapsulate all details of an operation in a separate object
 - Define instruction for applything the command (either in the command itself, or elsewhere)
 - Optionally define instructions for undoing the command
 - Can create composite commands (a.k.a. macros)
 
 - Interpreter 
- Barring simple cases, an interpreter acts in two stages
 - Lexing turns text into a set of tokens
 - Parsing tokens into meaningful construct
 
 - Iterator 
- An iterator specified how you can traverse an object
 - Stateful iterators cannot be recursive
 - yield allows for much more succinct iteration
 
 - Mediator 
- Create the mediator and have each object in the system refer to it 
- E.g., in a property
 
 - Mediator engages in bidirectional communication with its connected components
 - Mediator has functions the components can call
 - Components have functions the mediator can call
 - Event processing (e.g., Rx) libraries make communication easier to implement
 
 - Create the mediator and have each object in the system refer to it 
 - Memento 
- Mementos are used to roll back states arbitrarily
 - A memento is simply a token/handle class with typically no function of its own
 - A memento is not required to expose directly the state(s) to which it reverts the system
 - Can be used to implement undo/redo
 
 - Observer 
- Observer is an intrusive approach: an observable must provide an event to subscribe to
 - Subsciption and unsubscription with additional/removal of items in list
 - Property notifications are easy: dependent property notifications are tricky
 
 - State 
- Given sufficient complexity, it pays to formally define possible states and events/triggers
 - Can define 
- State entry/exit behaviors
 - Action when a particular event causes a transition
 - Guard conditions enabling/disabling a transition
 - Default action when no transitions are found for an event
 
 
 - Strategy 
- Define an algorithm at a high level
 - Define the interface you expect each strategy to follow
 - Provide for dynamic composition of strategies in the resulting object
 
 - Template 
- Define an algorithm at a high level in parent class
 - Define constituent parts as abstract methods/properties
 - Inherit the algorthm class, providing the necessary ovverides
 
 - Visitor 
- OOP double-dispatch approach is not necessary in Python
 - Make a visitor, decorating each 'overload' with @visitor
 - Call visit() and the entire structure gets traversed
 
 
 - Chain of Responsibility 
 
| No | Name | Exercise | Test | Description | 
|---|---|---|---|---|
| 1. | Adapter | Text and Exercise for Adapter | Test Adapter | Allows objects with incompatible interfaces to collaborate. | 
| 2. | Builder | Text and Exercise for Builder | Test Builder | Lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code. | 
| 3. | Command | Text and Exercise for Command | Test Command | Turns a request into a stand-alone object that contains all information about the request. This transformation lets you parameterize methods with different requests, delay or queue a request's execution, and support undoable operations. | 
| 4. | Decorator | Text and Exercise for Decorator | Test Decorator | Lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors. | 
| 5. | Factories (Factory Method and Abstract Factory) | Text and Exercise for Factories (Factory Method and Abstract Factory) | Test Factories (Factory Method and Abstract Factory) | Provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. Abstract - Lets you produce families of related objects without specifying their concrete classes. | 
| 6. | Iterator | Text and Exercise for Iterator | Test Iterator | Lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.). | 
| 7. | Observer | Text and Exercise for Observer | Test Observer | Lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they're observing. | 
| 8. | Prototype | Textand Exercise for Prototype | Test Prototype | Lets you copy existing objects without making your code dependent on their classes. | 
| 9. | Singleton | Textand Exercise for Singleton | Test Singleton | Lets you ensure that a class has only one instance, while providing a global access point to this instance. | 
| 10. | Strategy | Text and Exercise for Strategy | Test Strategy | Lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable. | 
| 11. | Template | Text and Exercise for Template | Test Template | Defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure. | 
- Course work and notes from Udemy course by Dmitri Nesteruk.
 
-  
MT - milovantomasevic.com
 -  
Certificate of Completion – Udemy - See credential
 
