一、介绍
工厂模式(Factory Pattern)是最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
二、简单工厂
统一使用一个类作为对外接口,根据参数的不同,去选择实例化不同的类。
"""
两个产品(两种类型的书)
"""
class TechnicalBooks(object):
"""技术书籍"""
def publish(self):
return "Python-Book"
class LiteraryBooks(object):
"""文学书籍"""
def publish(self):
return "Black Hole Book"
# 现在我们有两种类型的书,分别是TechnicalBooks和LiteraryBooks的书
# 按照我们平常的方法来实例化的话,此时创建对象时是会对客户端暴露真正创建的类
it_books = TechnicalBooks()
ly_books = LiteraryBooks()
# 这时我们就可以构造一个"简单工厂"把所有实例化的过程封装在里面,把真正实例的类隐藏起来
class SimpleFactory(object):
"""简单工厂"""
@staticmethod
def publish_book(name):
if name == 'technical':
return TechnicalBooks()
elif name == 'literary':
return LiteraryBooks()
it_books2 = SimpleFactory.publish_book('technical')
ly_books2 = SimpleFactory.publish_book('literary')
简单工厂的好处在于,把不同类的实例化统一到一个"工厂",即不对外暴露真正的创建类,也提供了一个对外的统一接口。
但是简单工厂也有一个缺点,那就是违背了solid的 "开闭原则",假如我们还需要增加一种书籍,那就必须要对简单工厂SimpleFactory进行源码的修改,
简单工厂使用场景:
例如:某个系统,已经明确就只会有MySQL、Redis、MongoDB三个数据库的情况下,可以直接使用简单工厂模式。
三、工厂方法
上面的简单工厂我们已经知道了,如果新增一些类型的时候会违背软件设计中的开闭原则,但是我们希望在扩展新的类时,不要修改原有的代码。这个时候我们可以在简单工厂的基础上把SimpleFactory抽象成不同的工厂,每个工厂对应生成自己的产品,这就是工厂方法。
"""
两个产品(两种类型的书)
"""
import abc
# 真正进行实例化的类
class TechnicalBooks(object):
"""技术书籍"""
def publish(self):
return "Python-Book"
class LiteraryBooks(object):
"""文学书籍"""
def publish(self):
return "Black Hole Book"
# 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
class AbstractFactory(metaclass=abc.ABCMeta):
"""抽象工厂"""
@abc.abstractmethod
def publish_book(self):
pass
class TechnicalFactory(AbstractFactory):
"""技术书籍工厂"""
def publish_book(self):
return TechnicalBooks()
class LiteraryFactory(AbstractFactory):
"""文学书籍工厂"""
def publish_book(self):
return LiteraryBooks()
it_books2 = TechnicalFactory().publish_book()
ly_books2 = LiteraryFactory().publish_book()
这样每个工厂就只负责生产自己的产品,避免了在新增产品时需要修改工厂的代码,遵循了"开闭原则",如果需要新增产品时,只需要增加相应的工厂即可。
比如要新增一种小说类型的书籍,只需新增一个NovelBooks类和NovelFactory类。
工厂方法的使用场景:
- 当系统中拥有的子类很多,并且以后可能还需要不断拓展增加不同的子类时。
- 当设计系统时,还不能明确具体有哪些类时。
在工厂方法中,使用者不需要知道具体的产品类名,只需要知道其对应的工厂即可。
四、抽象工厂
工厂方法解决了"开闭原则"的问题,但是我们出版书籍之前肯定还会有其他的步骤,比如印刷。 如果每一个步骤我们就要写一个对应的工厂类,那我们就会需要创建很多很多类了。 因此为了解决这个问题,我们就要需要抽象工厂类,让一个工厂可以生产同一类的多个产品或多个动作(步骤),这就是抽象工厂。
"""
两个产品(两种类型的书)
"""
import abc
# 印刷书籍
class PrintingTechnicalBooks(object):
"""印刷技术书籍"""
def printing(self):
return "Print-Python-Book"
class PrintingLiteraryBooks(object):
"""印刷文学书籍"""
def printing(self):
return "Print Black Hole Book"
# 出版书籍
class TechnicalBooks(object):
"""出版技术书籍"""
def publish(self):
return "Python-Book"
class LiteraryBooks(object):
"""出版文学书籍"""
def publish(self):
return "Black Hole Book"
# 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
class AbstractFactory(metaclass=abc.ABCMeta):
"""抽象工厂"""
@abc.abstractmethod
def print_book(self):
pass
@abc.abstractmethod
def publish_book(self):
pass
class TechnicalFactory(AbstractFactory):
"""技术书籍工厂"""
def print_book(self):
return PrintingTechnicalBooks()
def publish_book(self):
return TechnicalBooks()
class LiteraryFactory(AbstractFactory):
"""文学书籍工厂"""
def print_book(self):
return PrintingLiteraryBooks()
def publish_book(self):
return LiteraryBooks()
# 实例化工厂对象
it = TechnicalFactory()
ly = LiteraryFactory()
# 印刷书籍
it_print = it.print_book()
ly_print = ly.print_book()
# 出版书籍
it_publish = it.publish_book()
ly_publish = ly.publish_book()
抽象工厂模式与工厂方法模式的区别:
抽象工厂中的一个工厂对象可以负责多个不同产品对象的创建
抽象工厂的使用场景:
- 当多个产品(步骤)集合在一起,组成产品族时。
- 对于一个产品族,如果只想显示接口而不是实现时。
来源:https://www.cnblogs.com/Zzbj/p/15778464.html |