Shape-Factory-Pattern
Sat 17 May 2025
import pyutil as pyu
pyu.get_local_pyinfo()
'conda env: ml311; pyv: 3.11.10 (main, Oct 3 2024, 07:29:13) [GCC 11.2.0]'
print(pyu.ps2("haystack-ai ollama-haystack python-dotenv"))
haystack-ai==2.8.0
ollama-haystack is not installed in the current environment.
python-dotenv==0.21.0
from abc import ABC, abstractmethod
# Step 1: Define an abstract base class (interface)
class Shape(ABC):
@abstractmethod
def draw(self):
pass
# Step 2: Create concrete implementations of the Shape interface
class Circle(Shape):
def draw(self):
return "Drawing a Circle"
class Square(Shape):
def draw(self):
return "Drawing a Square"
class Rectangle(Shape):
def draw(self):
return "Drawing a Rectangle"
# Step 3: Create a Factory class to generate objects
class ShapeFactory:
@staticmethod
def get_shape(shape_type):
if shape_type == "circle":
return Circle()
elif shape_type == "square":
return Square()
elif shape_type == "rectangle":
return Rectangle()
else:
raise ValueError(f"Unknown shape type: {shape_type}")
# Client Code
if __name__ == "__main__":
# Use the factory to create shapes
factory = ShapeFactory()
shape1 = factory.get_shape("circle")
print(shape1.draw()) # Output: Drawing a Circle
shape2 = factory.get_shape("square")
print(shape2.draw()) # Output: Drawing a Square
shape3 = factory.get_shape("rectangle")
print(shape3.draw()) # Output: Drawing a Rectangle
Drawing a Circle
Drawing a Square
Drawing a Rectangle
# Singleton + Factory
from abc import ABC, abstractmethod
# Abstract Base Class
class Shape(ABC):
@abstractmethod
def draw(self):
pass
# Concrete Implementation: Circle
class Circle(Shape):
_instance = None # Class-level variable to store the singleton instance
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if not hasattr(self, "initialized"): # To prevent reinitialization
print("Initializing Circle...")
self.initialized = True
def draw(self):
return "Drawing a Circle"
# Concrete Implementation: Square
class Square(Shape):
_instance = None # Class-level variable to store the singleton instance
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if not hasattr(self, "initialized"): # To prevent reinitialization
print("Initializing Square...")
self.initialized = True
def draw(self):
return "Drawing a Square"
# Factory Class
class ShapeFactory:
@staticmethod
def get_shape(shape_type):
if shape_type == "circle":
return Circle() # Singleton behavior for Circle
elif shape_type == "square":
return Square()
else:
raise ValueError(f"Unknown shape type: {shape_type}")
# Client Code
if __name__ == "__main__":
factory = ShapeFactory()
# First time creating Circle
shape1 = factory.get_shape("circle")
print(shape1.draw()) # Output: Drawing a Circle
# Reusing the same Circle instance
shape2 = factory.get_shape("circle")
print(shape2.draw()) # Output: Drawing a Circle
# Reusing the same Circle instance
shape2 = factory.get_shape("square")
print(shape2.draw()) # Output: Drawing a Circle
# Reusing the same Circle instance
shape2 = factory.get_shape("square")
print(shape2.draw()) # Output: Drawing a Circle
# Verifying both instances are the same
print(shape1 is shape2) # Output: True
Initializing Circle...
Drawing a Circle
Drawing a Circle
Initializing Square...
Drawing a Square
Drawing a Square
False
Decorator
import time
from abc import ABC, abstractmethod
# Step 1: Define an abstract base class (interface)
class Shape(ABC):
@abstractmethod
def draw(self):
pass
# Step 2: Create concrete implementations of the Shape interface
class Circle(Shape):
def draw(self):
return "Drawing a Circle"
class Square(Shape):
def draw(self):
return "Drawing a Square"
class Rectangle(Shape):
def draw(self):
return "Drawing a Rectangle"
# Decorator for measuring execution time
def execution_time_wrapper(original_method):
def wrapper(*args, **kwargs):
start_time = time.time()
result = original_method(*args, **kwargs)
end_time = time.time()
execution_time = end_time - start_time
formatted_execution_time = f"{execution_time:.6f}"
print(f"{original_method.__name__} executed in {formatted_execution_time} seconds")
return result, formatted_execution_time
return wrapper
# Step 3: Create a Factory class to generate objects
class ShapeFactory:
@staticmethod
def get_shape(shape_type):
if shape_type == "circle":
shape = Circle()
elif shape_type == "square":
shape = Square()
elif shape_type == "rectangle":
shape = Rectangle()
else:
raise ValueError(f"Unknown shape type: {shape_type}")
# Dynamically wrap the draw method
shape.draw = execution_time_wrapper(shape.draw)
return shape
# Client Code
if __name__ == "__main__":
# Use the factory to create shapes
factory = ShapeFactory()
shape1 = factory.get_shape("circle")
print(shape1.draw()) # Output: Drawing a Circle with execution time
shape2 = factory.get_shape("square")
print(shape2.draw()) # Output: Drawing a Square with execution time
shape3 = factory.get_shape("rectangle")
print(shape3.draw()) # Output: Drawing a Rectangle with execution time
draw executed in 0.000000 seconds
('Drawing a Circle', '0.000000')
draw executed in 0.000000 seconds
('Drawing a Square', '0.000000')
draw executed in 0.000000 seconds
('Drawing a Rectangle', '0.000000')
Score: 10
Category: mythraki