Python设计模式之工厂模式丨【生长吧!Python】
1、什么是简单工厂模式
专门定义一个类来负责创建其他类的实例,根据参数的不同创建不同类的实例,被创建的实例通常具有共同的父类,这个模式叫简单工厂模式(Simple FactoryPattern)。简单工厂模式又称为静态工厂方法模式。
2、工厂模式设计思想
日常生活中,我们通过咖啡机制作咖啡,加入不同风味的咖啡豆就产生不同口味的咖啡。这一过程就如同一个工厂一样,我们加入不同的配料,就会生产出不同的产品,这就是程序设计中工厂模式的概念。在工厂模式中,用来创建对象的类叫工厂类,被创建的对象的类称为产品类。
3、工厂三姐妹
工厂模式三姐妹:简单工厂模式、工厂方法模式、抽象工厂模式。这三种模式可以理解为同一种编程思想的三个版本,从简单到高级不断升级。工厂方法模式是简单工厂模式的升级,抽象工厂模式又是工厂方法模式的升级。
3.1、简单工厂模式
这是最简单的一个版本,只有一个工厂类 SimpleFactory,类中有一个静态的创建方法createProduct,该方法根据参数传递过来的类型值(type)或名称(name)来创建具体的产品(子类)对象。
1、定义
定义一个创建对象(实例化对象)的接口,通过参数来决定创建哪个类的实例。
2、代码
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class Product(metaclass=ABCMeta):
"""产品"""
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
@abstractmethod
def feature(self):
pass
class ProductA(Product):
"""产品A"""
def __init__(self, name):
super().__init__(name)
def feature(self):
return "ProductA"
class ProductB(Product):
"""产品B"""
def __init__(self, name):
super().__init__(name)
def feature(self):
return "ProductB"
class SimpleFactory:
"""简单工厂模式"""
@staticmethod
def createProduct(name):
"""通过staticmethod装饰器修饰来定义一个静态方法"""
if name == "ProductA":
product = ProductA("产品A")
elif name == "ProductB":
product = ProductB("产品B")
else:
raise ValueError("不支持的参数:%s" % name)
return product
def testSimpleFactory():
product_a = SimpleFactory.createProduct("ProductA")
print("产品工厂创建了:", product_a.getName(), product_a.feature())
product_b = SimpleFactory.createProduct("ProductB")
print("产品工厂创建了:", product_b.getName(), product_b.feature())
testSimpleFactory()
3、输出结果
产品工厂创建了: 产品A ProductA
产品工厂创建了: 产品B ProductB
4、类图
SimpleFactory是工厂类,负责创建对象。Product是要创建的产品的抽象类,负责定义统一的接口。ProductA和ProductB是具体的产品类型。
5、优缺点
优点:
(1)实现简单、结构清晰。
(2)抽象出一个专门的类来负责某类对象的创建,分割出创建的职责,不能直接创建具体的对象,只需传入适当的参数即可。
(3)使用者可以不关注具体对象的类名称,只需知道传入什么参数可以创建哪些需要的对象。
缺点:
(1)不易拓展,一旦添加新的产品类型,就不得不修改工厂的创建逻辑。不符合“开放封闭”原则,如果要增加或删除一个产品类型,就要修改switch...case...(或if...else...)的判断代码。
(2)当产品类型较多时,工厂的创建逻辑可能过于复杂,switch...case...(或if...else...)判断会变得非常多。一旦出错可能造成所有产品创建失败,不利于系统的维护。
6、应用场景
(1)产品具有明显的继承关系,且产品的类型不太多。
(2)所有的产品具有相同的方法和类似的属性,使用者不关心具体的类型,只希望传入合适的参数能返回合适的对象。尽管简单工厂模式不符合“开放-封闭”原则,但因为它简单,所以仍然能在很多项目中看到它。
3.2、工厂方法模式
工厂方法模式是简单工厂模式的一个升级版本,为解决简单工厂模式不符合“开放-封闭”原则的问题,我们对 SimpleFactory 进行了一个拆分,抽象出一个父类Factory,并增加多个子类分别负责创建不同的具体产品。
1、定义
定义一个创建对象(实例化对象)的接口,让子类来决定创建哪个类的实例。工厂方法使一个类的实例化延迟到其子类。
2、代码
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class Product(metaclass=ABCMeta):
"""产品"""
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
@abstractmethod
def feature(self):
pass
class ProductA(Product):
"""产品A"""
def __init__(self, name):
super().__init__(name)
def feature(self):
return "ProductA"
class ProductB(Product):
"""产品B"""
def __init__(self, name):
super().__init__(name)
def feature(self):
return "ProductB"
class Factory(metaclass=ABCMeta):
"""抽象工厂"""
@abstractmethod
def createProduct(self, name):
pass
class ProductAFactory(Factory):
"""产品A的工厂"""
def createProduct(self, name):
# 返回A产品实例
return ProductA(name)
class ProductBFactory(Factory):
"""产品B的工厂"""
def createProduct(self, name):
# 返回B产品实例
return ProductB(name)
def testSimpleFactory():
factory = ProductAFactory()
product_a = factory.createProduct("产品A")
print("产品工厂A创建了:", product_a.getName())
factory = ProductBFactory()
product_b = factory.createProduct("产品B")
print("产品工厂B创建了:", product_b.getName())
testSimpleFactory()
3、输出结果
产品工厂A创建了: 产品A
产品工厂B创建了: 产品B
4、类图
Product是要创建的产品的抽象类,ProductA和ProductB是具体的产品类型。Factory是所有工厂的抽象类,负责定义统一的接口。ProductAFactory和ProductBFactory是具体的工厂类,分别负责产品ProductA和ProductB的创建。
5、优缺点
优点:
(1)解决了简单工厂模式不符合“开放-封闭”原则的问题,使程序更容易拓展。
(2)实现简单。
缺点:
对于有多种分类的产品,或具有二级分类的产品,工厂方法模式并不适用。
多种分类:如我们有一个电子白板程序,可以绘制各种图形,那么画笔的绘制功能可以理解为一个工厂,而图形可以理解为一种产品;图形可以根据形状分为直线、矩形、椭圆等,也可以根据颜色分为红色图形、绿色图形、蓝色图形等。
二级分类:如一个家电工厂,它可能同时生产冰箱、空调和洗衣机,那么冰箱、空调、洗衣机属于一级分类;而洗衣机又可分为高效型的和节能型的,高效型洗衣机和节能型洗衣机就属于二级分类。
6、应用场景
(1)客户端不知道它所需要的对象的类。
(2)工厂类希望通过其子类来决定创建哪个具体类的对象。
因为工厂方法模式简单且易拓展,因此在项目中应用得非常广泛,在很多标准库和开源项目中都能看到它的影子。
3.3、抽象工厂模式
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式不能解决具有二级分类的产品的创建问题,抽象工厂模式就是用来解决这一问题的。
1、定义
提供一个创建一系列相关或相互依赖的对象的接口,而无须指定它们的具体类。
2、代码
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class Product(metaclass=ABCMeta):
"""产品抽象类"""
@abstractmethod
def feature(self):
pass
class ProductA(Product):
"""产品A抽象类"""
@abstractmethod
def feature(self):
pass
class ProductA1(ProductA):
"""产品A1类"""
def feature(self):
return "ProductA1"
class ProductA2(ProductA):
"""产品A2类"""
def feature(self):
return "ProductA2"
class ProductB(Product):
"""产品B抽象类"""
@abstractmethod
def feature(self):
pass
class ProductB1(ProductB):
"""产品B1类"""
def feature(self):
return "ProductB1"
class ProductB2(ProductB):
"""产品B2类"""
def feature(self):
return "ProductB2"
class AbstractFactory(metaclass=ABCMeta):
"""抽象工厂类"""
@abstractmethod
def createProductA(self):
pass
@abstractmethod
def createProductB(self):
pass
class Factory1(AbstractFactory):
"""工厂1生产1系列产品"""
def createProductA(self):
# 返回A1产品实例
return ProductA1()
def createProductB(self):
# 返回B1产品实例
return ProductB1()
class Factory2(AbstractFactory):
"""工厂2生产2系列产品"""
def createProductA(self):
# 返回A2产品实例
return ProductA2()
def createProductB(self):
# 返回B2产品实例
return ProductB2()
def testSimpleFactory():
factory = Factory1()
product_a1 = factory.createProductA()
product_b1 = factory.createProductB()
print("产品工厂1创建了:", product_a1.feature(), product_b1.feature())
factory = Factory2()
product_a2 = factory.createProductA()
product_b2 = factory.createProductB()
print("产品工厂2创建了:", product_a2.feature(), product_b2.feature())
testSimpleFactory()
3、输出结果
产品工厂1创建了: ProductA1 ProductB1
产品工厂2创建了: ProductA2 ProductB2
4、类图
抽象工厂模式适用于有多个系列且每个系列有相同子分类的产品。我们定义一个抽象的工厂类AbstractFactory,AbstractFactory中定义生产每个系列产品的方法;而两个具体的工厂实现类Factory1和Factory2分别生产子分类1的每一系列产品和子分类2的每一系列产品。
5、优缺点
优点:
解决了具有二级分类的产品的创建。
缺点:
(1)如果产品的分类超过二级,如三级甚至更多级,抽象工厂模式将会变得非常臃肿。
(2)不能解决产品有多种分类、多种组合的问题。
6、应用场景
(1)系统中有多于一个的产品族,而每次只使用其中某一产品族。
(2)产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。
【生长吧!Python】有奖征文火热进行中:https://bbs.huaweicloud.com/blogs/278897
- 点赞
- 收藏
- 关注作者
评论(0)