This repository has been archived by the owner on Apr 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from MGTheTrain/feature/design-patterns
[Feature] - Design pattern samples in Python
- Loading branch information
Showing
12 changed files
with
405 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
class Target(ABC): | ||
"""Interface for the client to interact with.""" | ||
@abstractmethod | ||
def request(self): | ||
"""Abstract method to be implemented by concrete classes.""" | ||
pass | ||
|
||
class Adaptee: | ||
"""Contains some useful behavior with an incompatible interface.""" | ||
def specific_request(self): | ||
"""Method representing the specific request of the Adaptee.""" | ||
print("Adaptee's specific request") | ||
|
||
class Adapter(Target): | ||
"""Adapts the interface of Adaptee to the Target interface.""" | ||
def __init__(self, adaptee: Adaptee): | ||
"""Initialize the Adapter with an instance of Adaptee.""" | ||
self.adaptee = adaptee | ||
|
||
def request(self): | ||
"""Implement the request method to bridge between Target and Adaptee.""" | ||
self.adaptee.specific_request() | ||
|
||
def main(): | ||
"""Entry point of the program.""" | ||
adaptee = Adaptee() | ||
adapter = Adapter(adaptee) | ||
adapter.request() | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import threading | ||
|
||
class Product: | ||
"""Represents the complex object being constructed.""" | ||
def __init__(self): | ||
self.parts = [] | ||
self.mutex = threading.Lock() | ||
|
||
def add_part(self, part): | ||
"""Method to add a part to the product.""" | ||
with self.mutex: | ||
self.parts.append(part) | ||
|
||
def show_parts(self): | ||
"""Method to display the parts of the product.""" | ||
with self.mutex: | ||
print("Product parts:", ", ".join(self.parts)) | ||
|
||
class Builder: | ||
"""Interface for creating parts of a complex object.""" | ||
def build_part_a(self): | ||
"""Method to build part A.""" | ||
raise NotImplementedError | ||
|
||
def build_part_b(self): | ||
"""Method to build part B.""" | ||
raise NotImplementedError | ||
|
||
def get_product(self): | ||
"""Method to retrieve the constructed product.""" | ||
raise NotImplementedError | ||
|
||
class ConcreteBuilder(Builder): | ||
"""Implements the Builder interface to construct a specific product.""" | ||
def __init__(self): | ||
self.product = Product() | ||
|
||
def build_part_a(self): | ||
"""Method to build part A.""" | ||
self.product.add_part("Part A") | ||
|
||
def build_part_b(self): | ||
"""Method to build part B.""" | ||
self.product.add_part("Part B") | ||
|
||
def get_product(self): | ||
"""Method to retrieve the constructed product.""" | ||
return self.product | ||
|
||
class Director: | ||
"""Responsible for using the builder to construct a complex object.""" | ||
def __init__(self, builder: Builder): | ||
self.builder = builder | ||
|
||
def construct(self): | ||
"""Method to construct the product using the assigned builder.""" | ||
self.builder.build_part_a() | ||
self.builder.build_part_b() | ||
|
||
def main(): | ||
"""Entry point of the program.""" | ||
builder = ConcreteBuilder() | ||
director = Director(builder) | ||
|
||
threads = [] | ||
|
||
def thread_func(): | ||
"""Function to be executed by each thread.""" | ||
director.construct() | ||
product = builder.get_product() | ||
product.show_parts() | ||
|
||
for _ in range(5): | ||
t = threading.Thread(target=thread_func) | ||
threads.append(t) | ||
t.start() | ||
|
||
for thread in threads: | ||
thread.join() | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
class Component(ABC): | ||
@abstractmethod | ||
def operation(self): | ||
"""Abstract method representing the operation.""" | ||
pass | ||
|
||
class ConcreteComponent(Component): | ||
def operation(self): | ||
"""Concrete implementation of the operation.""" | ||
print("ConcreteComponent operation") | ||
|
||
class Decorator(Component): | ||
def __init__(self, component: Component): | ||
""" | ||
Constructor for the Decorator class. | ||
Args: | ||
component (Component): The component to be decorated. | ||
""" | ||
self.component = component | ||
|
||
def operation(self): | ||
"""Delegates the operation to the wrapped component.""" | ||
self.component.operation() | ||
|
||
class ConcreteDecorator(Decorator): | ||
def operation(self): | ||
"""Overrides the operation to add additional behavior.""" | ||
super().operation() # Calls the wrapped component's operation | ||
print("Added behavior in ConcreteDecorator") | ||
|
||
class AnotherConcreteDecorator(Decorator): | ||
def operation(self): | ||
"""Overrides the operation to add different behavior.""" | ||
super().operation() # Calls the wrapped component's operation | ||
print("Added behavior in AnotherConcreteDecorator") | ||
|
||
class AnotherConcreteDecorator2(Decorator): | ||
def operation(self): | ||
"""Overrides the operation to add another behavior.""" | ||
super().operation() # Calls the wrapped component's operation | ||
print("Added behavior in AnotherConcreteDecorator2") | ||
|
||
def main(): | ||
component = ConcreteComponent() | ||
decorated = ConcreteDecorator(component) | ||
decorated.operation() | ||
|
||
print("\n") | ||
|
||
another_decorated = AnotherConcreteDecorator(decorated) | ||
another_decorated.operation() | ||
|
||
print("\n") | ||
|
||
another_decorated2 = AnotherConcreteDecorator2(another_decorated) | ||
another_decorated2.operation() | ||
|
||
if __name__ == "__main__": | ||
main() |
37 changes: 37 additions & 0 deletions
37
python/design-patterns/dependency-injection/dependency-injection.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
class Service(ABC): | ||
@abstractmethod | ||
def execute(self): | ||
"""Abstract method representing the execution of a service.""" | ||
pass | ||
|
||
class Client: | ||
def __init__(self, service): | ||
""" | ||
Constructor for the Client class. | ||
Args: | ||
service (Service): The service to be used by the client. | ||
""" | ||
self.service = service | ||
|
||
def do_something(self): | ||
"""Performs an action using the provided service.""" | ||
self.service.execute() | ||
|
||
class ConcreteService(Service): | ||
def execute(self): | ||
"""Concrete implementation of the service execution.""" | ||
print("Executing ConcreteService") | ||
|
||
def main(): | ||
# Create a concrete service | ||
service = ConcreteService() | ||
# Create a client with the concrete service | ||
client = Client(service) | ||
# Perform an action using the service | ||
client.do_something() | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
class Observer(ABC): | ||
@abstractmethod | ||
def update(self, message): | ||
"""Method called by the Subject when its state changes.""" | ||
pass | ||
|
||
class Subject: | ||
def __init__(self): | ||
self.observers = [] | ||
|
||
def attach(self, observer): | ||
"""Attaches an observer to the subject.""" | ||
self.observers.append(observer) | ||
|
||
def detach(self, observer): | ||
"""Detaches an observer from the subject.""" | ||
self.observers.remove(observer) | ||
|
||
def notify(self, message): | ||
"""Notifies all observers when the subject's state changes.""" | ||
for observer in self.observers: | ||
observer.update(message) | ||
|
||
class ConcreteObserver1(Observer): | ||
def update(self, message): | ||
"""Prints a message upon receiving an update from the Subject.""" | ||
print("ConcreteObserver1 received message:", message) | ||
|
||
class ConcreteObserver2(Observer): | ||
def update(self, message): | ||
"""Prints a message upon receiving an update from the Subject.""" | ||
print("ConcreteObserver2 received message:", message) | ||
|
||
def main(): | ||
# Create a subject | ||
subject = Subject() | ||
|
||
# Create observers | ||
observer1 = ConcreteObserver1() | ||
observer2 = ConcreteObserver2() | ||
|
||
# Attach observers to the subject | ||
subject.attach(observer1) | ||
subject.attach(observer2) | ||
|
||
# Notify observers | ||
subject.notify("Hello Observers!") | ||
|
||
# Detach observer2 | ||
subject.detach(observer2) | ||
|
||
# Notify observers again | ||
subject.notify("Observers, are you there?") | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import threading | ||
|
||
class Singleton: | ||
_instance = None # Private static variable to hold the singleton instance | ||
_lock = threading.Lock() # Lock for thread safety | ||
|
||
@staticmethod | ||
def getInstance(): | ||
""" | ||
Static method to retrieve the singleton instance. | ||
Returns: | ||
Singleton: The singleton instance. | ||
""" | ||
if Singleton._instance is None: | ||
with Singleton._lock: # Acquire the lock for thread safety | ||
if Singleton._instance is None: # Double check to ensure thread safety | ||
print("Singleton instance created") | ||
Singleton._instance = Singleton() | ||
return Singleton._instance | ||
|
||
def printMessage(self): | ||
"""Method to print a test message.""" | ||
print("Test...") | ||
|
||
def threadFunc(): | ||
"""Function to be executed by each thread.""" | ||
singleton = Singleton.getInstance() | ||
singleton.printMessage() | ||
|
||
def main(): | ||
threads = [] | ||
for _ in range(5): | ||
threads.append(threading.Thread(target=threadFunc)) | ||
|
||
for thread in threads: | ||
thread.start() | ||
|
||
for thread in threads: | ||
thread.join() | ||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.