Python之工厂模式

一、介绍

工厂模式(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()

抽象工厂模式与工厂方法模式的区别:

    抽象工厂中的一个工厂对象可以负责多个不同产品对象的创建 

 

抽象工厂的使用场景

  • 当多个产品(步骤)集合在一起,组成产品族时。
  • 对于一个产品族,如果只想显示接口而不是实现时。

 

posted @ 2022-01-08 15:51  我用python写Bug  阅读(7596)  评论(0编辑  收藏  举报