As you may know by now, we are integrating the design patterns we've studied into a practical project: building a smart home system. Throughout this final unit, you'll learn how to create and adapt various smart home devices using the Singleton, Builder, Composite, and Abstract Factory patterns. By the end, you will have a solid understanding of how these design patterns can make your smart home system more efficient, modular, and easier to maintain.
Singleton Pattern:
Singleton
) with a static method to hold the single instance.getInstance
method to manage instance creation and access.Builder Pattern:
SmartHomeDevice
) for the object.SmartHomeDeviceBuilder
) with methods to set object properties and a method to return the final object.Composite Pattern:
DeviceComponent
) for the composite structure.LeafDevice
for individual objects and CompositeDevice
for composite objects.Abstract Factory Pattern:
SmartDeviceFactory
).LightFactory
, FanFactory
) to create specific sensor and actuator objects.To start, we implement the Singleton pattern in Python to ensure that a class has only one instance and provides a global point of access to it.
Python1class Singleton: 2 __instance = None 3 4 @staticmethod 5 def getInstance(): 6 if Singleton.__instance is None: 7 Singleton.__instance = Singleton() 8 # Additional initialization code can go here 9 return Singleton.__instance 10 11# Usage 12singleton1 = Singleton.getInstance() 13singleton2 = Singleton.getInstance() 14print(singleton1 is singleton2) # Output: True
The getInstance
method checks if an instance exists and creates one if it does not.
Next, we use the Builder pattern to construct complex SmartHomeDevice
objects step by step.
Python1class SmartHomeDevice: 2 def __init__(self): 3 self.sensors = [] 4 self.actuators = [] 5 self.name = "" 6 7class SmartHomeDeviceBuilder: 8 def __init__(self): 9 self.__device = SmartHomeDevice() 10 11 def add_sensors(self, sensors): 12 self.__device.sensors = sensors 13 return self 14 15 def add_actuators(self, actuators): 16 self.__device.actuators = actuators 17 return self 18 19 def set_name(self, name): 20 self.__device.name = name 21 return self 22 23 def build(self): 24 return self.__device 25 26# Usage 27builder = SmartHomeDeviceBuilder() 28device = (builder 29 .set_name('Smart Light') 30 .add_sensors(['Light Sensor']) 31 .add_actuators(['LED']) 32 .build()) 33print(device.name) # Output: Smart Light
The SmartHomeDeviceBuilder
class provides methods to set device properties and construct the final SmartHomeDevice
.
Now, we implement the Composite pattern to manage individual and composite objects uniformly.
Python1class DeviceComponent: 2 def __init__(self, name): 3 self.name = name 4 5 def operation(self): 6 pass 7 8class LeafDevice(DeviceComponent): 9 def operation(self): 10 print(f'Leaf {self.name} operation') 11 12class CompositeDevice(DeviceComponent): 13 def __init__(self, name): 14 super().__init__(name) 15 self.children = [] 16 17 def add(self, component): 18 self.children.append(component) 19 20 def operation(self): 21 print(f'Composite {self.name} operation') 22 for child in self.children: 23 child.operation() 24 25# Usage 26leaf1 = LeafDevice('Light') 27leaf2 = LeafDevice('Fan') 28composite = CompositeDevice('Room') 29composite.add(leaf1) 30composite.add(leaf2) 31composite.operation() 32# Output: 33# Composite Room operation 34# Leaf Light operation 35# Leaf Fan operation
The CompositeDevice
class allows us to treat individual DeviceComponent
objects uniformly as part of a composite structure.
Finally, we implement the Abstract Factory pattern to create families of related objects without specifying their concrete classes.
Python1class SmartDeviceFactory: 2 def create_sensor(self): 3 pass 4 5 def create_actuator(self): 6 pass 7 8class LightFactory(SmartDeviceFactory): 9 def create_sensor(self): 10 return LightSensor() 11 12 def create_actuator(self): 13 return LEDActuator() 14 15class FanFactory(SmartDeviceFactory): 16 def create_sensor(self): 17 return TemperatureSensor() 18 19 def create_actuator(self): 20 return MotorActuator() 21 22class LightSensor: 23 def __init__(self): 24 print('Light Sensor created') 25 26class LEDActuator: 27 def __init__(self): 28 print('LED Actuator created') 29 30class TemperatureSensor: 31 def __init__(self): 32 print('Temperature Sensor created') 33 34class MotorActuator: 35 def __init__(self): 36 print('Motor Actuator created') 37 38# Usage for LightFactory 39light_factory = LightFactory() 40light_sensor = light_factory.create_sensor() # Output: Light Sensor created 41light_actuator = light_factory.create_actuator() # Output: LED Actuator created 42 43# Usage for FanFactory 44fan_factory = FanFactory() 45fan_sensor = fan_factory.create_sensor() # Output: Temperature Sensor created 46fan_actuator = fan_factory.create_actuator() # Output: Motor Actuator created
The LightFactory
and FanFactory
classes implement methods to create specific sensor and actuator objects.
Implementing Singleton, Builder, Composite, and Abstract Factory patterns in our smart home system allows us to create, organize, and manage devices in a structured and reusable manner. The Singleton pattern ensures a single instance of a class, the Builder pattern provides a flexible solution for object creation, the Composite pattern handles both individual and composite objects uniformly, and the Abstract Factory pattern creates families of related objects. This approach makes our smart home system more modular, flexible, and easier to maintain and extend.