python设计模式【2】-工厂模式

  1. UML类图简介
  2. 设计模式的分类
  3. 面向对象的设计原则
  4. python设计模式【1】-单例模式
  5. python设计模式【2】-工厂模式
  6. python设计模式【3】-门面模式
  7. python设计模式【4】-代理模式
  8. python设计模式【5】-观察者模式
  9. python设计模式【6】-命令模式
  10. python设计模式【7】-模板方法模式
  11. python设计模式【8】-模型·视图·控制器-复合模式
  12. python设计模式【9】-状态模式

一、工厂模式的优点

  1. 松耦合,即对象的创建可以独立于类的实现。
  2. 客户端无需了解创建对象的类,但是可以照样使用它来创建对象,只需要知道需要传递的接口、方法和参数,就能够创建所需类型的对象。简化了客户端的实现。
  3. 可以轻松地在工厂中添加其他类来创建其他类型的对象,无需更改客户端代码,有时客户端只需传递另一个参数就行。
  4. 工厂还可以重用现有对象。但是,如果客户端直接创建对象的话,总是创建一个新对象。

二、工厂模式的三种变体

  • 简单工厂模式:允许接口创建对象,但不会暴露对象的创建逻辑。
  • 工厂方法模式:允许接口创建对象,但使用哪个类来创建对象,则是由子类决定的。
  • 抽象工厂模式:是一个能够创建一系列相关的对象而无需指定/公开其具体类的接口,该模式能够提供其他工厂的对象,在其内部创建其他对象

1、简单工厂模式

示例代码如下:

# -*- coding:utf-8 -*-
from abc import ABCMeta, abstractmethod


class Animal(metaclass=ABCMeta):
    @abstractmethod
    def do_say(self):
        pass


class Dog(Animal):
    def do_say(self):
        print("dog bhow bhow")


class Cat(Animal):
    def do_say(self):
        print("cat meow meow")


class ForestFactory(object):
    def make_sound(self, object_type):
        return eval(object_type)().do_say()


if __name__ == '__main__':
    ff = ForestFactory()
    animal = input("which animal should make_sound Dog or Cat?")
    ff.make_sound(animal)

创建一个为Animal的抽象产品,带有方法do_say(),利用Animal接口创建了两种产品(Dog,Cat),并实现了do_say方法来提供这些动物相应的叫声。ForestFactory是一个带有make_sound()方法的工厂,根据客户端传递的参数类型,可以在运行时创建适当的Animal实例,并输出正确的声音。

2、工厂方法模式

(1)了解工厂方法模式

  • 定义了一个接口来创建对象,但是工厂本身并不复杂创建对象,而是将这一任务交由子类来完成,即子类决定了要实例化哪些类
  • Factory方法的创建是通过继承而不是实例化来完成的
  • 工厂方法使设计更加具有可定制性,它可以返回相同的实例或子类,而不是某种类型的对象

  在该UML中,有一个包含factoryMethod()方法的抽象类Creator,factoryMethod()方法负责创建指定类型的对象。ConcreteCreator类提供了一个实例Creator抽象类的factoryMethod()方法,这种方法可以在运行时修改已创建的对象。ConcreteCreator创建ConcreteProduct,并确保其创建的对象实现了Product,同时为Product接口中的所有方法提供相应的实现。

  简言之,Creator接口的factoryMethod()方法和ConcreteCreator类共同决定了要创建Product的哪个子类。因此,工厂方法模式定义了一个接口来创建对象,但具体实例化哪个类则是由它的子类决定的。

(2)实现工厂方法

# -*- coding:utf-8 -*-
from abc import ABCMeta, abstractmethod


# 接口Product
class Section(metaclass=ABCMeta):
    @abstractmethod
    def describe(self):
        pass


# 定义多个ConcreteProduct
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")


# 创建了一个抽象类(Creator) Profile,提供了一个工厂方法createProfile()
class Profile(metaclass=ABCMeta):
    def __init__(self):
        self.sections = []
        self.createProfile()

    @abstractmethod
    def createProfile(self):
        pass

    def getSections(self):
        return self.sections

    def addSections(self, section):
        self.sections.append(section)


# 创建了两个ConcreteCreator,即linkedin, facebook,每个类都实现了createProfile抽象方法,
# 由该方法在运行时实际创建(实例化)多个区(ConcreteProduct)
class linkedin(Profile):
    def createProfile(self):
        self.addSections(PersonalSection())
        self.addSections(PatentSection())
        self.addSections(PublicationSection())


class facebook(Profile):
    def createProfile(self):
        self.addSections(PersonalSection)
        self.addSections(AlbumSection)

# 客户端代码
if __name__ == '__main__':
    profile_type = input("which profile LinkedIn or FaceBook?")
    profile = eval(profile_type.lower())()
    print("creating profile..", type(profile).__name__)
    print("profile has sections --", profile.getSections())

 

上述代码段的输出如下:

(3)工厂方法模式的优缺点

  •  使得代码更加通用,不是单纯地实例化某个类。实现哪些类取决于接口(Product),而不是ConcreteProduct类。
  •     它们是松耦合的,创建对象的代码与使用它们的代码的分开的。客户端完全不用关心要传递哪些参数以及需要实例化哪些类。由于添加新类更加容易,降低了维护成本。

 3、抽象工厂方法模式

(1)了解抽象工厂模式

    抽象工厂的主要目的是提供一个接口来创建一系列相关对象,而无需指定具体的类。工厂方法将创建实例的任务委托给了子类,而抽象工厂方法的目标是创建一系列相关对象。

(2)UML

            

         在该UML中,ConcreteFactory1和ConcreteFactory2是通过AbstractFactory接口创建的,并创建实例ConcreteProduct1和ConcreteProduct2、AnotherConcreteProduct1和            AnotherConcreteProduct2;ConcreteProduct1和ConcreteProduct2是通过AbstractProduct接口创建的,而AnotherConcreteProduct1和AnotherConcreteProduct2则是通过            AnotherAbstractProduct接口创建的。

        实际上,抽象工厂模式不仅确保客户端与对象的创建相互隔离,同时还确保客户端能够使用创建的对象。但是,客户端只能通过接口访问对象。

(3)实现抽象工厂模式

# -*- coding:utf-8 -*-
from abc import ABCMeta, abstractmethod


# AbstractFactory
class PizzaFactory(metaclass=ABCMeta):
    # 具有两个抽象方法,它们需要通过ConcreteFactory实现
    @abstractmethod
    def creatVegPizza(self):
        pass

    @abstractmethod
    def creatNonVegPizza(self):
        pass


# 两个ConcreteFactory,实现了抽象方法
class IndianPizzaFactory(PizzaFactory):
    def creatVegPizza(self):
        return DeluxVeggiePizza()

    def creatNonVegPizza(self):
        return ChickenPizza()


class USPizzaFactory(PizzaFactory):
    def creatVegPizza(self):
        return MexicanVegPizza()

    def creatNonVegPizza(self):
        return HamPizza()


# 定义抽象类AbstractProduct
class VegPizza(metaclass=ABCMeta):

    @abstractmethod
    def prepare(self, VegPizza):
        pass


# 定义抽象类AnotherAbstractProduct
class NonVegPizza(metaclass=ABCMeta):
    @abstractmethod
    def serve(self, VegPizza):
        pass


# 定义ConcreteProduct1
class DeluxVeggiePizza(VegPizza):
    def prepare(self):
        print("prepare", type(self).__name__)


# 定义ConcreteProduct2
class ChickenPizza(NonVegPizza):
    def serve(self, VegPizza):
        print(type(self).__name__, "is served with chicken on", type(VegPizza).__name__)


# AnotherConcreteProduct1
class MexicanVegPizza(VegPizza):
    def prepare(self):
        print("prepare", type(self).__name__)


# AnotherConcreteProduct2
class HamPizza(NonVegPizza):
    def serve(self, VegPizza):
        print(type(self).__name__, "is served with chicken on", type(VegPizza).__name__)


class PizzaStore:
    def __init__(self):
        pass

    def makePizzas(self):
        for factory in [IndianPizzaFactory(), USPizzaFactory()]:
            self.factory = factory
            self.NonVegPizza = self.factory.creatNonVegPizza()
            self.VegPizza = self.factory.creatVegPizza()
            self.VegPizza.prepare()
            self.NonVegPizza.serve(self.VegPizza)


if __name__ == '__main__':
    pizza = PizzaStore()
    pizza.makePizzas()

 

运行结果如下:

工厂方法与抽象工厂对比:

 


参考:

《python设计模式》(第2版)https://www.epubit.com/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值