diff --git a/.gitattributes b/.gitattributes index dfe0770..f5618cc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ # Auto detect text files and perform LF normalization * text=auto +*.ipynb text eol=lf diff --git a/design_patterns/README.md b/design_patterns/README.md new file mode 100644 index 0000000..e2c4f68 --- /dev/null +++ b/design_patterns/README.md @@ -0,0 +1,33 @@ +Design patterns in Python are reusable solutions to common software design problems. They are categorized into three main types: + +### **1. Creational Patterns (Object Creation)** + +* **Singleton** : Ensures a class has only one instance and provides a global access point. +* **Factory Method** : Defines an interface for creating an object but allows subclasses to alter the type of objects created. +* **Abstract Factory** : Provides an interface for creating families of related or dependent objects without specifying their concrete classes. +* **Builder** : Separates object construction from its representation, allowing the same process to create different representations. +* **Prototype** : Creates new objects by copying an existing object, reducing object creation cost. + +### **2. Structural Patterns (Class/Object Composition)** + +* **Adapter** : Converts one interface to another, making incompatible interfaces work together. +* **Bridge** : Decouples abstraction from its implementation so both can evolve independently. +* **Composite** : Composes objects into tree structures to represent part-whole hierarchies. +* **Decorator** : Dynamically adds responsibilities to an object at runtime. +* **Facade** : Provides a simplified interface to a complex subsystem. +* **Flyweight** : Reduces memory usage by sharing large numbers of small, similar objects. +* **Proxy** : Controls access to another object, adding functionalities like lazy initialization, security, or logging. + +### **3. Behavioral Patterns (Object Interaction & Responsibilities)** + +* **Chain of Responsibility** : Passes a request along a chain of handlers, each deciding to process or pass it. +* **Command** : Encapsulates requests as objects, allowing request queueing, undo, and logging. +* **Interpreter** : Defines a grammar and interprets sentences in that grammar. +* **Iterator** : Provides a way to access elements sequentially without exposing internal structure. +* **Mediator** : Reduces dependencies between objects by centralizing communication. +* **Memento** : Captures an object's state to restore it later without exposing its details. +* **Observer** : Defines a dependency where multiple objects are notified of state changes. +* **State** : Allows an object to change its behavior when its internal state changes. +* **Strategy** : Defines a family of algorithms and makes them interchangeable. +* **Template Method** : Defines a skeleton of an algorithm in a method but allows subclasses to override parts of it. +* **Visitor** : Separates algorithm from object structure, allowing operations on elements without modifying their classes. diff --git a/design_patterns/singleton_dp.ipynb b/design_patterns/singleton_dp.ipynb new file mode 100644 index 0000000..172801b --- /dev/null +++ b/design_patterns/singleton_dp.ipynb @@ -0,0 +1,75 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1. Using a Metaclass (__call__ Method)\n", + "This is the most Pythonic way to implement Singleton." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "Instance1\n", + "Instance1\n" + ] + } + ], + "source": [ + "class SingletonMeta(type):\n", + " \"\"\"A metaclass for creating singleton classes.\"\"\"\n", + " _instances = {}\n", + "\n", + " def __call__(cls, *args, **kwargs):\n", + " \"\"\"Ensures only one instance of the class is created.\"\"\"\n", + " if cls not in cls._instances:\n", + " cls._instances[cls] = super().__call__(*args, **kwargs)\n", + " return cls._instances[cls]\n", + "\n", + "\n", + "class Singleton(metaclass=SingletonMeta):\n", + " \"\"\"A class using the Singleton pattern via metaclass.\"\"\"\n", + " def __init__(self, value: str):\n", + " self.value = value\n", + "\n", + "\n", + "# Testing Singleton behavior\n", + "singleton1 = Singleton(\"Instance1\")\n", + "singleton2 = Singleton(\"Instance2\")\n", + "\n", + "print(singleton1 is singleton2) # True (both are the same instance)\n", + "print(singleton1.value) # \"Instance1\"\n", + "print(singleton2.value) # \"Instance1\" (value does not change)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}