• 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()

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

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

    抽象工厂的使用场景

    • 当多个产品(步骤)集合在一起,组成产品族时。
    • 对于一个产品族,如果只想显示接口而不是实现时。
  • 相关阅读:
    MessageFormat使用记录
    在IDEA中使用MyBatis Generator逆向工程生成代码
    mybatis报错invalid types () or values ()解决方法
    关于jrebel碰到的一次问题记录
    I/O限制异步操作
    线程基础和异步执行计算限制
    模板方法模式(Head first 设计模式——7)
    适配器模式和外观模式(head first设计模式——6)
    命令模式(head first 设计模式5)
    工厂模式——(Head first设计模式4)
  • 原文地址:https://www.cnblogs.com/Zzbj/p/15778464.html
Copyright © 2020-2023  润新知