python设计模式之工厂模式

一、了解工厂模式

        1.优点

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

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

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

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


        2.分类

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

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

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


二、简单工厂模式

        1.UML图


        2.代码

# -*- 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("Bhow Bhow!!")

# 猫类,继承动物类
class Cat(Animal):
    def do_say(self):
        print("Meow Meow!!")

## forest factory defined
class ForestFactory(object):
    def make_sound(self, object_type):
        print(eval(object_type))
        return eval(object_type)().do_say()

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


        3.解析

               3.1 代码中的ForestFactory就是传说中的工厂,我们输入,Cat或者Dog,就会通过它直接调用具体的类中的make_sound方法。
               3.2 eval函数

                          eval函数可以将字符串直接当然有效的表达式,当然如果此处不用eval函数也可以采用if elif else 的形式进行对输入的判定,和类方法的调用。但此例中eval方式显然更加优雅。


三、工厂方法模式

        1.概念

               1.1 定义接口来创建对象,工厂本身并不负责创建对象,而是将这一任务交由子类完成,即子类决定了要实例化哪些类。

               1.2 Factory方法的创建是通过继承而不是通过实例化来完成的。

               1.3 工厂方法使设计更加具有可定制性。它可以返回相同的实例或子类,而不是某种类型的对象(就像简单工厂方法那样)

         2.UML图



         3.代码

# -*- coding: UTF-8 -*-
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)

# 继承Profile,实例化具体类(实例化了具体创建哪些简历)
class linkedin(Profile):
    def createProfile(self):
        self.addSections(PersonalSection())
        self.addSections(PatentSection())
        self.addSections(PublicationSection())

# 继承Profile,实例化具体类
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 orFaceBook]")
    profile = eval(profile_type.lower())()
    print("Creating Profile..", type(profile).__name__)
    print("Profile has sections --", profile.getSections())

    

         4.解析

                 4.1 工厂方法里面的工厂不创建类只提供接口。

                 4.2 当我们输入Linkedin后发生了什么?

                           4.2.1 linkedin类被实例化:Profile中的__init__中的创建createProfile被调用(linkedin的createProfile被调用)->addSections被调用->section列表增加

                           4.2.2 这里再次强调,Profile只提供了相关接口,实现是由linkedin子类来做的。

         5.优点

                 5.1 它具有更大的灵活性,使得代码更加通用,因为它不是单纯地实例化某个类。这样实现哪些类取决于接口。

                 5.2 松耦合,因为创建对象的代码与使用它的代码是分开的。客户端无需关心传递哪些参数以及需要实例化哪些类。由于添加新类更加容易,所以降低了维护成本。

四、抽象工厂模式

       1.UML图



       2.代码

# -*- coding: UTF-8 -*-
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()]:
            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()






       3.解析

             3.1 与工厂方法的主要区别是,将工厂多了一层抽象。它创建的不是一个对象是一类对象。

             3.2本例中,当创建工厂后,会同步创建蔬菜披萨和非蔬菜披萨两个类。


五、工厂方法与抽象工厂方法

        工厂方法:

                   1.它向客户端开放了一个创建对象的方法。

                   2.它使用继承和子类来决定要创建哪个对象

                   3.工厂方法用于创建一个产品

抽象工厂方法:

                   1.抽象工厂包换了一个或者多个工厂方法来创建一系列的相关对象

                   2.它使用组合将创建对象的任务委托给其他类

                   3.抽象工厂用于创建相关产品系列


本系列项目代码地址:Python-design-pattern

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若云流风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值