暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OOP设计模式Python实现--创建型模式之工厂模式

稻壳编程 2020-02-27
256

作者简介

211工程院校贵州大学管理学院硕士研究生、互联网金融行业资深DevOps研发工程师. 曾在国内多家知名互联网公司 平安科技、微众银行、顺丰科技、魅族任职. 具有多年国内一线互联网公司自动化运维平台设计与开发经验。



OOP设计模式Python实现

创建型模式--工厂模式

前言:

创建型模式(Creational Pattern)对类的实例化过程进行抽象,能够将代码中对象的创建和对象的使用分离。外界对于这些对象不需清楚其具体的实现细节只需知道它们的共同接口即可,这样开发出代码结构更加清晰且符合单一职责原则。在日常工作中"需求总是变化的",如果我们无法控制产品经理不拍脑袋提需求,那么就应在代码的开发过程中应将需求的变化当做常态,进而开发出能够适应变化的代码。尽己所能的规避"经常变化的需求和不能变化的代码"这一矛盾。本文介绍的工厂模式属于创建型模式的一种,它主要分为三类,分别是简单工厂模式、工厂模式、抽象工厂模式。

 1 

简单工厂模式

简单工厂模式(Simple Factory Pattern)专门定义了一个工厂类负责创建其他类的实例,在工厂类中可以根据参数的不同返回不同类的实例,通过工厂创建的实例通常具有共同的父类。简单工厂模式代码由以下几种角色组成:

  • 工厂(Factory)角色:它是简单工厂模式的核心负责实现创建所有实例的内部逻辑,工厂类可以被外界直接调用并创建所需的产品对象

  • 抽象产品(Product)角色:由简单工厂模式所创建的所有对象的抽象父类,负责描述所有实例所拥有的公共接口

  • 具体产品(Concrete Product)角色:简单工厂模式创建的具体目标,所有创建的对象都是充当这个角色的某个具体类的实例

 2 

示例代码(简单工厂模式)

某城市组织志愿者和学生参加学雷锋做好事从来不留姓名活动,要求在指定的区域打扫卫生或做好人好事,根据这一需求场景,应用简单工厂模式编码出以下代码

输出:

在简单工厂模式中,创建什么对象只需要向工厂类传入相应参数即可,而无须知道创建细节。若需求发生了变化要中学生也加入做好事的行列,此时就需要增加一个中学生类(MiddleStudent),同时也要修改工厂类中的maps,这样代码就违背了"开闭原则"。当产品类型较多时,会造成工厂类的职责过重、逻辑复杂不利于代码的扩展和维护,这是简单工厂模式的缺点。

 3 

工厂模式

工厂方法模式是简单工厂的进一步深化,在工厂方法模式中不再通过一个统一的工厂类来创建所有对象,而是每个对象都有一个与之对应的工厂。在上面简单工厂模式代码的示例中,具体对象在maps属性中全部直接创建,这将会带来性能开销;工厂方法模式使用继承自抽象工厂角色的多个子类来分担对象创建的压力,这样的代码结构更加灵活,当有新的产品加入时,只要继承抽象产品角色、抽象工厂角色的约定来开发新的子类即可。

工厂模式角色组成:

  • 抽象工厂角色:工厂方法模式的核心,是具体工厂角色必须实现的接口或是必须继承的父类

  • 具体工厂角色:它含有和具体业务逻辑有关的代码。被客户端调用以创建对应的具体产品的对象

  • 抽象产品角色:它是具体产品继承的父类或者是实现的接口

  • 具体产品角色:具体工厂角色所创建的对象就是此角色的实例

 4 

示例代码(工厂模式)

输出:

以上使用工厂模式思路编码的代码更具灵活性,当需求发生变化需要中学生加入学雷锋做好事的行动中时,需要创建一个中学生类和一个中学生工厂类,虽然过程比较繁琐,但是这样的代码是符合"开闭原则"的。通过判断输入类型,并返回相应实例这一过程在简单工厂模式中是在工厂类中完成的,而在工厂模式中是在客户端中实现的。

 5 

抽象工厂模式

抽象工厂模式是工厂方法模式的一种扩展,非常适用于"产品角色"扩展的场景,但不适用于"产品族"扩展的场景,抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定具体类的情况下,创建多个产品族中的产品对象。例如某代工厂分别为苹果和三星代工产品(品牌为产品族),已知两个厂商均有手机和平板电脑(产品角色)两种类型的产品。由于生产手机和生产平板的工艺不同,所以该代工厂开辟了两条生产线,分别用来生产手机和平板。

抽象工厂模式代码角色构成:

  • AbstractFactory(抽象工厂):  声明了一组用于创建对象的抽象方法

  • ConcreteFactory(具体工厂): 实现了在抽象工厂中声明的创建对象的方法生成一组具体对象

  • AbstractProduct(抽象产品): 为每种对象声明接口定义了对象所应具有的业务方法

  • ConcreteProduct(具体产品):定义具体工厂生产的具体对象

下面还是先看一个具体实例。

 6 

示例代码(抽象工厂模式)

输出:

前面介绍到抽象工厂模式不适合扩展"产品族"的场景,若此时添加一个新品牌华为的话,代码将会如何改动呢?首先需要在抽象工厂类中声明新方法createHuaweiProduct()

由于抽象工厂基类中的代码发生了变化,那么继承它的子类都要发生变化,这就违背了"开闭原则"。但如果扩展产品角色时,比如扩充了"电脑"角色时,只需要新建各厂家的电脑产品类和一个电脑工厂即可,都是对现有代码扩展而非修改,这样就符合了开闭原则,所以抽象工厂模式不适用于扩展"产品族"而适用于扩展"产品角色"。

 7 

结束语

如果本文可以对您的工作学习带来帮助,请扫描左侧赞赏码以资鼓励作者;文章勘误请扫描右侧二维码联系作者。

文章转载自稻壳编程,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论