第3章 工厂模式:建立创建对象的工厂

1.了解工厂模式

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

  • 松耦合:对象的创建可独立于类的实现
  • 客户端无需了解创建对象的类,只需知道需要传递的接口、方法和参数。简化了客户端的实现
  • 可以轻松地在工厂中添加其他类来创建其他类型对象,无需更改客户端代码。
  • 可重用现有对象

2.简单工厂模式

允许接口创建对象,但不会暴露对象的创建逻辑。
参看如下示例:

from abc import ABCMeta,abstractmethod

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

class Dog(Animal):
    def do_say(self):
        print('汪汪')

class Cat(Animal):
    def do_say(self):
        print('喵喵')

class ForestFactory:
    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)

输出如下:

Which animal should make_sound,Dog or Cat?>? Dog
汪汪

元类是类的类,其实例就是一个类。Python中一切皆对象,默认的元类是type,其他都是type的实例。
其中,ABCMeta是Python的特殊元类,用于生成抽象基类(Abstract)。Animal是一个抽象基类,带有方法do_say()。利用Animal接口创建了两种产品,并实现了do_say()方法提供这些动物的叫声。ForestFactory是一个带有make_sound()方法的工厂。根据客户端传递的参数类型,它就可以在运行时创建适当的Animal实例,并输出正确的声音。

3 工厂方法模式

以下几点可以帮助我们了解工厂方法模式:

  • 定义一个接口创建对象,但工厂本身并不负责创建对象,而是将这一任务交由子类完成,即子类决定要实例化哪些内容
  • Factory方法的创建时通过继承而不是通过实例化完成的
  • 工厂方法使设计更加具有可定制性。它可以返回相同的实例或子类,而不是某种类型的对象。
    参看如下例子:
from abc import ABCMeta,abstractmethod

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')

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)

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 you'd like to create?[LinkedIn or Facebook]")
    profile=eval(profile_type.lower())()
    print("Creating Profile..",type(profile).__name__)
    print("Profile has sections --",profile.getSections())

解析:
假设想在不同类型的社交网络上为个人或公司建立简介。那么,每个简介都有某些特定的组成章节,同时也有公共的章节。简而言之,我们要通过将正确的区添加到相应的简介中来创建不同类型的简介。
创建一个Section抽象类来定义一个区是关于哪方面内容的。这个Section抽象类被称为接口Product。
随后建立PersonalSection、AlbumSection、PatentSection和PublicationSection类。这些类被称为ConcreteProduct。都是Section的子类。
创建一个名为Profile的抽象类Creator。Profile抽象类提供一个工厂方法,即createProfile()。createProfile()方法应该由ConcreteClass实现,来实际创建带有适当区的简介。Profile抽象类不知道每个简介应具有哪些区,所以让子类来决定这些事情。
创建两个ConcreteCreator类,linkedin和facebook。每个类实现createProfile()抽象方法,由该方法在运行时实际创建多个区。
Creator接口的factoryMethod()方法和ConcreteCreator类工图决定了要创建Product的哪些子类。因此,工厂方法模式定义了一个接口来创建对象,但具体实例化哪个类则是由它的子类决定。
工厂方法使一个类的实例化延迟到其子类,可以不修改原有的工厂类。工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现具体类。工厂方法将简单工厂的内部逻辑判断移到了客户端代码来进行。
工厂方法模式的优点:

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

4 抽象工厂模式

主要目的:提供一个接口创建一系列相关对象,而无需指定具体的类。工厂方法将创建实例的任务委托给了子类,而抽象工厂方法的目标是创建一系列相关对象。
实际上,抽象工厂模式不仅确保客户端与对象的创建相互隔离,同时还确保客户端能够使用创建的对象。但是,客户端只能通过接口访问对象。
如果要使用一个系列中的多个产品,那么抽象工厂模式能够帮助客户端一次使用来自一个产品/系列的多个对象。
例如:正在开发的应用应该是平台无关的,则它需要对各种依赖项进行抽象处理,包括操作系统、文件系统调用,等等。抽象工厂模式负责为整个平台创建所需的服务,如此,客户端就不必直接创建平台对象。
参看如下实例:

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):
        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()]:
            self.factory=factory
            self.NonVegPizza=self.factory.createNonVegPizza()
            self.VegPizza=self.factory.createVegPizza()
            self.VegPizza.prepare()
            self.NonVegPizza.serve(self.VegPizza)

pizza=PizzaStore()
pizza.makePizzas()

输出如下:

Prepare  DeluxVeggiePizza
ChickenPizza  is served with Chicken on  DeluxVeggiePizza
Prepare  MexicanVegPizza
HamPizza  is served with Ham on  MexicanVegPizza

上例中:

  • 抽象工厂:PizzaFactory
  • 具体工厂:IndianPizzaFactory和USPizzaFactory
  • 抽象产品:VegPizza和NonVegPizza
  • 具体产品:DeluxVeggiePizza和MexicanVegPizza、ChickenPizza和HamPizza

抽象工厂模式结构图

5 工厂方法与抽象工厂方法

工厂方法抽象工厂方法
向客户端开放了一个创建对象的方法包含一个或多个工厂方法来创建一个系列的相关对象
使用继承和子类来决定要创建哪个产品使用组合将创建对象的任务委托给其他类
工厂方法用于创建一个产品抽象工厂方法用于创建相关产品的系列

抽象工厂方法的优点与缺点
优点

  • 便于交换产品系列,由于具体工厂类在一个应用中只需要在初始化时出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置
  • 让具体的创建实例过程与客户端分离,客户端通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值