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

(完)