python设计模式:工厂模式

时间:2025-03-15 16:23:11

概述

         在面向对象编程中,术语“工厂”表示一个负责创建其他类型对象的类。通常情况下,作为一个工厂的类有一个对象以及与它关联的多个方法。客户端使用某些参数调用此方法,之后,工厂会据此创建所需类型的对象,然后将它们返回给客户端。

        工厂模式有3种变体:

        (1)简单工厂模式,用于生成一系列具有相同类型属性的产品。

        (2)工厂方法模式,用于生成一系列产品,不同产品可包含不同类型的属性。

        (3)抽象工厂模式,用于生成多个相关系列的产品,同一个系列的不同产品也可以包含不同类型的属性。

        工厂模式的应用场景:在任何需要生成复杂对象的地方,都可以使用工厂模式。对于简单的,只需要简单的new一个对象即可,无需使用工厂模式。如果简单对象使用工厂模式,需要引入一个工厂类,增加系统的复杂度。

实战

一、简单工厂模式

         允许接口创建对象,但不会暴露对象的创建逻辑。工厂可以帮助开发人员创建不同类型的对象,而不是直接将对象实例化。

from abc import ABCMeta, abstractmethod

# 创建Animal抽象类
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def do_say(self):
        pass

# 创建Dog类
class Dog(Animal):
    def do_say(self):
        print('Bhow Bhow!')

# 创建Cat类
class Cat(Animal):
    def do_say(self):
        print('Meow Meow!')

# 创建工厂类
class ForestFactory:
    def make_sound(self, object_type):
        return eval(object_type)().do_say()

if __name__ == '__main__':
    ff = ForestFactory()
    ff.make_sound('Cat')

        ABCMeta是python的特殊元类,用来生成类Abstract,@abstractmethod为抽象方法,含@abstractmethod的类不能被实例化,继承了含@abstractmethod方法的子类必须复写所有@abstractmethod装饰的方法。

        上面代码中,Animal是一个抽象的基类,它带有方法do_say()。我们利用Animal接口创建了两种产品(Cat和Dog),并实现了do_say()方法来提供这些动物相应的叫声。

        ForestFactory是一个带有make_sound()方法的工厂。根据客户端传递的参数类型,它就可以在输出正确的声音。

二、工厂方法模式

        工厂方法模式定义了一个接口来创建对象,但具体实例化哪个类则是由它的子类决定的。 

        假设我们需要在LinkedIn、Facebook为个人或公司建立简介。那么,每个简介都有某些特定的组成章节。在LinkedIn的简介中,包含个人信息、申请的专利和出版的作品。在Facebook的简介中,包含个人信息、相册。

from abc import ABCMeta, abstractmethod

# 创建Section抽象类
class Section(metaclass=ABCMeta):
    @abstractmethod
    def describe(self):
        pass

# 创建个人信息部分类
class PersonalSection(Section):
    def describe(self):
        print('Personal Section')

# 创建相册部分类
class AlbumSection(Section):
    def describe(self):
        print('Album Section')

# 创建专利部分类
class PatentSection(Section):
    def describe(self):
        print('Patent Section')

# 创建出版作品部分类
class PublicationSection(Section):
    def describe(self):
        print('Publication Section')

# 创建Profile抽象类
class Profile(metaclass=ABCMeta):
    def __init__(self):
         = []
        ()

    @abstractmethod
    def createProfile(self):
        pass

    def getSections(self):
        return [type(i).__name__ for i in ]  # 返回简介拥有的所有部分的信息

    def addSections(self, section):
        (section)  # 给简介添加各部分

# 创建LinkedIn简介类
class linkedin(Profile):
    def createProfile(self):
        (PersonalSection())  # 添加个人部分
        (PatentSection())  # 添加专利部分
        (PublicationSection())  # 添加出版部分

# 创建Facebook简介类
class facebook(Profile):
    def createProfile(self):
        (PersonalSection())  # 添加个人部分
        (AlbumSection())  # 添加相册部分

if __name__ == '__main__':
    profile_type = input("Which Profile you'd like to create?[LinkedIn or FaceBook]")
    profile = eval(profile_type.lower())()
    print('Create Profile...', type(profile).__name__)
    print('Profile has sections --', ())

        在上面代码中,我们首先创建了Section抽象类,基于它创建了PersonalSection、AlbumSection、PatentSection和PublicationSection等用于描述简介章节的类。然后又创建了抽象类Profile,基于它创建了linkedin和facebook两个类,用于实例化它们所包含的简介类。

 三、抽象工厂模式

        抽象工厂模式的主要目的是提供一个接口来创建一系列相关对象,而无需指定具体的类。抽象工厂模式确保客户端与对象的创建相互隔离,同时还确保客户端能够使用创建的对象。

        假设我们开了一家披萨店,供应印式披萨和美式披萨,其中又各自都包含素食披萨和非素食披萨。

from abc import ABCMeta, abstractmethod

# 创建披萨工厂抽象类
class PizzaFactory(metaclass=ABCMeta):
    @abstractmethod
    def createVegPizza(self):
        pass

    @abstractmethod
    def createNonVegPizza(self):
        pass

# 创建印式披萨工厂类
class IndianPizzaFactory(PizzaFactory):
    def createVegPizza(self):
        return DeluxVeggiePizza()

    def createNonVegPizza(self):
        return ChickenPizza()

# 创建美式披萨类
class USPizzaFactory(PizzaFactory):
    def createVegPizza(self):
        return MexicanVegPizza()

    def createNonVegPizza(self):
        return HamPizza()

# 创建素食披萨抽象类
class VegPizza(metaclass=ABCMeta):
    @abstractmethod
    def prepare(self, VegPizza):
        pass

# 创建非素食披萨抽象类
class NonVegPizza(metaclass=ABCMeta):
    @abstractmethod
    def serve(self, VegPizza):
        pass

# 创建美味蔬菜披萨类,准备美味蔬菜披萨
class DeluxVeggiePizza(VegPizza):
    def prepare(self):
        print('Prepare ', type(self).__name__)

# 创建鸡肉披萨类,将素食披萨搭配上鸡肉
class ChickenPizza(NonVegPizza):
    def serve(self, VegPizza):
        print(type(self).__name__, " is served with Chicken on ", type(VegPizza).__name__)

# 创建墨西哥蔬菜披萨类
class MexicanVegPizza(VegPizza):
    def prepare(self):
        print('Prepare ', type(self).__name__)

# 创建火腿披萨类,将素食披萨搭配上火腿
class HamPizza(NonVegPizza):
    def serve(self, VegPizza):
        print(type(self).__name__, " is served with Ham on ", type(VegPizza).__name__)

# 创建披萨商店类
class PizzaStore:
    def __init__(self):
        pass

    def makePizzas(self):
        for factory in [IndianPizzaFactory(), USPizzaFactory()]:
             = factory  # 实例化披萨工厂
             = ()  # 实例化素食披萨
             = ()  # 实例化非素食披萨
            ()  # 准备素食披萨
            ()  # 将肉/火腿搭配到素食披萨上


if __name__ == '__main__':
    pizza = PizzaStore()  # 实例化披萨商店
    ()  # 制作披萨

总结

工厂模式的优点

        1)松耦合,即对象的创建可以独立于类的实现。

        2)客户端无需了解创建对象的类,但是照样可以使用它来创建对象。它只需要知道需要传递的接口、方法和参数,就能够创建所需类型的对象了。这简化了客户端的实现。

        3)可以轻松地在工厂中添加其他类来创建其他类型类型的对象,而这无需更改客户端代码。最简单的情况下,客户端只需要传递另一个参数就可以了。

        4)工厂还可以重用现有对象。但是,如果客户端直接创建对象的话,总是创建一个新对象。

三种模式对比

        1)简单工厂模式:允许接口创建对象,但不会暴露对象的创建逻辑。

        2)工厂方法模式:允许接口创建对象,但使用哪个类来创建对象,则是交由子类决定的。

        3)抽象工厂模式:抽象工厂是一个能够创建一系列相关的对象而无需指定/公开其具体类的接口。该模式能够提供其他工厂的对象,在其内部创建其他对象。