python常用设计模式,单例和工厂设计模式Demo
单例模式
单例设计模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。
应用场景:日志记录、线程池、缓存等
优点:
- 全局访问:提供了一个全局访问点,便于控制实例数量。
- 资源节约:避免了创建多个对象时的资源浪费。
- 线程安全:在多线程环境中,可以保证只创建一个实例。
- 控制实例化:可以控制对象的创建过程。
缺点:
- 代码耦合:单例模式可能会隐藏一些依赖关系,导致代码耦合。
- 可测试性差:由于单例模式是全局的,这使得单元测试变得困难。
- 内存浪费:单例对象在程序的整个生命周期内都占用内存。
- 滥用:单例模式有时会被滥用,导致程序设计不灵活
方法一:使用模块的全局变量
Python模块是天然的单例,实现单例模式
singleton_module.py
class Singleton:
def __init__(self):
self.value = None
singleton_instance = Singleton()
在其他地方使用这个单例:
from singleton_module import singleton_instance
# 使用单例
singleton_instance.value = 42
print(singleton_instance.value)
方法二:使用类变量
通过类变量来跟踪实例,并在实例化时进行检查
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
if not hasattr(self, 'initialized'): # 确保只初始化一次
self.value = None
self.initialized = True
# 使用单例
singleton1 = Singleton()
singleton2 = Singleton()
singleton1.value = 42
print(singleton2.value) # 输出: 42
print(singleton1 is singleton2) # 输出: True
方法三:使用装饰器
通过装饰器来实现单例模式
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Singleton:
def __init__(self):
self.value = None
# 使用单例
singleton1 = Singleton()
singleton2 = Singleton()
singleton1.value = 42
print(singleton2.value) # 输出: 42
print(singleton1 is singleton2) # 输出: True
方法四:使用元类(Metaclass)
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
def __init__(self):
self.value = None
# 使用单例
singleton1 = Singleton()
singleton2 = Singleton()
singleton1.value = 42
print(singleton2.value) # 输出: 42
print(singleton1 is singleton2) # 输出: True
最常用和推荐的方法是使用类变量(方法二)和元类(方法四),因为它们在语义上更加清晰和直观
工厂设计模式
定义一个创建对象的接口,让子类决定实例化哪个类
优点:
- 代码解耦:将对象的创建与使用分离,使得代码更加灵活,易于扩展。
- 提高可维护性:当需要添加新的产品时,只需要添加一个具体的产品类和相应的具体工厂类即可,无需修改已有的工厂类。
- 封装性:隐藏了对象创建的细节,调用者只需要知道类型,不需要知道具体的实现。
缺点:
- 每增加一个产品类别,都需要增加一个产品类和一个工厂类,这可能导致类的数量成倍增加。
- 系统的抽象程度变得更高,对于简单的情况,可能会增加系统的复杂性。
代码样例:
"""例如,可以使用工厂函数或抽象基类(Abstract Base Classes, ABCs)来实现工厂模式"""
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
class Dog(Animal):
def sound(self):
return "Woof! "
class Cat(Animal):
def sound(self):
return "Meow! "
class AnimalFactory:
@staticmethod
def get_animal(animal_type):
if animal_type == "dog":
return Dog()
elif animal_type == "cat":
return Cat()
else:
raise ValueError("Invalid animal type")
# 使用工厂模式
factory = AnimalFactory()
dog = factory.create_animal("dog")
cat = factory.create_animal("cat")
print(dog.sound()) # 输出 "Woof!"
print(cat.sound()) # 输出 "Meow!"