Understanding Creational Design Patterns can be easier with examples. Creational Design Patterns focus on object creation mechanisms, providing flexibility and decoupling the object creation process from the client code. Here are three common Creational Design Patterns with examples:
-
Factory Method Pattern:
The Factory Method Pattern provides an interface for creating objects, but allows subclasses to decide which class to instantiate. It promotes loose coupling and encapsulation. Here’s an example:class Animal: def speak(self): pass class Dog(Animal): def speak(self): return "Woof!" class Cat(Animal): def speak(self): return "Meow!" class AnimalFactory: def create_animal(self, animal_type): if animal_type == "dog": return Dog() elif animal_type == "cat": return Cat() # Usage: factory = AnimalFactory() dog = factory.create_animal("dog") cat = factory.create_animal("cat") print(dog.speak()) # Output: Woof! print(cat.speak()) # Output: Meow!
In this example, the
AnimalFactory class encapsulates the object creation logic. It provides acreate_animal method that returns the appropriate animal object based on the input. -
Singleton Pattern:
The Singleton Pattern ensures that only one instance of a class is created and provides a global point of access to it. It is useful when you need to restrict object creation to a single instance. Here’s an example:class Singleton: _instance = None @staticmethod def get_instance(): if not Singleton._instance: Singleton._instance = Singleton() return Singleton._instance # Usage: instance1 = Singleton.get_instance() instance2 = Singleton.get_instance() print(instance1 is instance2) # Output: True
In this example, the
Singleton class ensures that only one instance is created by providing a static methodget_instance() that returns the same instance every time it is called. -
Builder Pattern:
The Builder Pattern separates the construction of complex objects from their representation, allowing the same construction process to create different representations. It simplifies object creation by providing a step-by-step approach. Here’s an example:class Pizza: def __init__(self): self.crust = None self.sauce = None self.toppings = [] def add_crust(self, crust): self.crust = crust def add_sauce(self, sauce): self.sauce = sauce def add_topping(self, topping): self.toppings.append(topping) def __str__(self): return f"Pizza with {self.crust} crust, {self.sauce} sauce, and {', '.join(self.toppings)} toppings" class PizzaBuilder: def __init__(self): self.pizza = Pizza() def set_crust(self, crust): self.pizza.add_crust(crust) return self def set_sauce(self, sauce): self.pizza.add_sauce(sauce) return self def add_topping(self, topping): self.pizza.add_topping(topping) return self def build(self): return self.pizza # Usage: builder = PizzaBuilder() pizza = builder.set_crust("thin").set_sauce("tomato").add_topping("cheese").add_topping("mushrooms").build() print(pizza)