设计模式之工厂模式

  工厂模式是设计模式中的经典模式,工厂模式又可分为以下三种类型:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

这三种模式可以理解为同一种编程思想的三个版本,从简单到高级不断升级。本文将着重介绍简单工厂模式

简单工厂模式

  简单工厂模式(Simple Factory Pattern)指的是专门定义一个类来负责创建其它类的实例,根据参数的不同创建不同类的实例,被创建的实例通常具有共同的父类。简单工厂模式又被称为静态工厂方法模式
  我们介绍一种最简单的简单工厂模式版本,只有一个工厂类SimpleFactory,类中有一个静态创建方法createProduct,该方法根据参数的名称(name)来创建具体的产品(子类)对象,其UML类图如下:
简单工厂类图
  让我们来看一个例子,比如我们有一个工厂(ToyFactory),需要根据玩具的名称,来加工出玩具鸭子(DuckToy)、玩具椅子(ChairToy)、玩具火车(TrainToy),其UML类图如下:
玩具加工类图
  Python实现代码:

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


# 玩具抽象类
class Toy(metaclass=ABCMeta):
    def __init__(self, name, price):
        self.__name = name
        self.__price = price

    def getName(self):
        return self.__name

    def getPrice(self):
        return self.__price

    @abstractmethod
    def getMaterial(self):
        pass


# 玩具鸭子
class DuckToy(Toy):
    def __init__(self, name, price):
        super(DuckToy, self).__init__(name, price)

    def getMaterial(self):
        return 'cotton'


# 玩具椅子
class ChairToy(Toy):
    def __init__(self, name, price):
        super(ChairToy, self).__init__(name, price)

    def getMaterial(self):
        return 'wood'


# 玩具火车
class TrainToy(Toy):
    def __init__(self, name, price):
        super(TrainToy, self).__init__(name, price)

    def getMaterial(self):
        return 'metal'


# 玩具加工类
class ToyFactory:
    def make_toy(self, toy_name):
        if toy_name == 'duck':
            toy = DuckToy('Duck', 20.0)
        elif toy_name == 'chair':
            toy = ChairToy('Chair', 50.0)
        elif toy_name == 'train':
            toy = TrainToy('Train', 100.0)
        else:
            raise ValueError('unsupported toy name, please choose duck, chair, train.')
        return toy


if __name__ == '__main__':
    duck_toy = ToyFactory().make_toy('duck')
    print('make a %s toy, its material: %s, its price: %s' % (duck_toy.getName(), duck_toy.getMaterial(), duck_toy.getPrice()))
    chair_toy = ToyFactory().make_toy('chair')
    print('make a %s toy, its material: %s, its price: %s' % (chair_toy.getName(), chair_toy.getMaterial(), chair_toy.getPrice()))
    train_toy = ToyFactory().make_toy('train')
    print('make a %s toy, its material: %s, its price: %s' % (train_toy.getName(), train_toy.getMaterial(), train_toy.getPrice()))

运行结果:

make a Duck toy, its material: cotton, its price: 20.0
make a Chair toy, its material: wood, its price: 50.0
make a Train toy, its material: metal, its price: 100.0

在该例子中,SimpleFactory为ToyFactory,方法make_toy根据玩具名称来加工不同的玩具类型,当玩具名称为duck时,加工玩具鸭子(DuckToy);当玩具名称为chair时,加工玩具椅子(ChairToy);当玩具名称为train时,加工玩具火车(TrainToy)。
  简单工厂模式的优点为:

  • 实现简单,结构清晰
  • 抽象出一个专门的类来负责某类对象的创建,分割出创建的职责,不能直接创建具体的对象,只需传入适当的参数即可
  • 使用者可以不关注具体对象的类名称,只需知道传入什么参数可以创建哪些需要的对象

其缺点为:

  • 不易拓展,一旦添加新的产品类型,就不得不修改工厂的创建逻辑,不符合“开放-封闭”原则
  • 当产品类型较多时,工厂的创建逻辑可能过于复杂

工厂方法模式

  工厂方法模式简单工厂模式的一个升级版本,其含义为定义一个创建对象(实例化对象)的接口,让子类来决定创建哪个类的实例。工厂方法使一个类的实例化延迟到其子类。
  为解决上述简单工厂模式不符合“开放-封闭”原则,我们对SimpleFactory进行拆分,抽象出一个父类Factory,并增加多个子类分别负责创建不同的具体产品,其UML类图如下:
工厂方法模式类图
工厂方法模式的优点为:

  • 解决了简单工厂模式不符合“开放-封闭”原则的问题,使程序更容易拓展
  • 实现简单

其缺点为:

  • 对于有多种分类的产品,或具有二级分类的产品,工厂方法模式不再适用

抽象工厂模式

  抽象工厂模式工厂方法模式的升级版本,可以解决具有二级分类的产品的创建问题,其UML类图可以设计如下:
抽象工厂模式类图
抽象工厂模式的优点为:

  • 解决了具有二级分类的产品的创建

其缺点为:

  • 如果产品分类超过二级,则该模式会变得臃肿
  • 不能解决产品有多种分类、多种组合的问题

参考文献

  1. 罗伟富 人人都懂设计模式:从生活中领悟设计模式(Python实现)[B],电子工业出版社

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/121.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

哈佛与冯诺依曼结构

1. 下图是典型的冯诺依曼结构 2. CPU分为三部分:ALU运算单元,CU控制单元,寄存器组。 3. 分析51单片机为何能使用汇编进行编程 51指令集(Instruction Set)是单片机CPU能够执行的所有指令的集合。在编写51单片机程序时&a…

Python打包成exe,文件太大问题解决办法(比保姆级还保姆级)

首先我要说一下,如果你不在乎大小,此篇直接别看了,因为我写过直接打包的,就多20M而已,这篇就别看了,点击查看不在乎大小直接打包这篇我觉得简单的令人发指 不废话,照葫芦画瓢就好 第1步&#…

Linux- 系统随你玩之--网络上的黑客帝国

文章目录1、前言2、TCPDump介绍2.1、问题来了: 所有用户都可以采用该命令吗?2.2、抓包原理2.3、特点2.3.1、参数化支持2.2.2、 TCP功能3、 服务器安装Tcpdump3.1、安装3.2、检查安装是否正常。4、tcpdump 命令4.1、常用功能选项4.2、输出内容5、实操5.1、…

初识C++需要了解的一些东西(2)

😁关注博主:翻斗花园第一代码手牛爷爷 😃Gitee仓库:牛爷爷爱写代码 目录🌍内联函数🌕内联函数概念🌖内联函数特性🌓auto关键字(C11)🌞类型别名⭐️auto简介☀️auto的使…

【数据库】数据库查询(进阶命令详解)

目录 1.聚合查询 1.1聚合函数 COUNT函数 SUM函数 AVG函数 MAX函数 MIN函数 1.2GROUP BY子句 1.3HAVING 2.联合查询 2.1内连接 2.2外连接 2.3自连接 2.4子查询 3.合并查询 写在前面: 文章截图均是每个代码显示的图。数据库对代码大小写不敏感&am…

java ArrayList源码分析(深度讲解)

ArrayList类的底层实现ArrayList类的断点调试空参构造的分步骤演示(重要)带参构造的分步骤演示一、前言大家好,本篇博文是对单列集合List的实现类ArrayList的内容补充。之前在List集合的万字详解篇,我们只是拿ArrayList演示了List…

C语言函数调用栈

栈溢出(stack overflow)是最常见的二进制漏洞,在介绍栈溢出之前,我们首先需要了解函数调用栈。 函数调用栈是一块连续的用来保存函数运行状态的内存区域,调用函数(caller)和被调用函数&#xf…

Java8使用Lambda表达式(流式)快速实现List转map 、分组、过滤等操作

利用java8新特性,可以用简洁高效的代码来实现一些数据处理。1 数据准备1.1 定义1个Fruit对象package com.wkf.workrecord.work;import org.junit.Test;import java.math.BigDecimal; import java.util.ArrayList; import java.util.List;/*** author wuKeFan* date …

Stable Diffusion加chilloutmixni真人图片生成模型,AI绘图杀疯了

上期图文教程,我们分享过AI绘图大模型Stable Diffusion以及中文版本文心AI绘画大模型的基础知识以及代码实现,截至到目前为止。Stable Diffusion模型已经更新到了V2.1版本,其文生图大模型也越来越火,其在2022年底,由AI绘制的图片被荣为国际大奖,让大家对AI绘画大模型也越…

Node.js-----使用express写接口

使用express写接口 文章目录使用express写接口创建基本的服务器创建API路由模块编写GET接口编写POST接口CROS跨域资源共享1.接口的跨域问题2.使用cros中间件拒绝跨域问题3.什么是cros4.cros的注意事项5.cros请求的分类JSONP接口1.回顾jsonp的概念和特点2.创建jsonp接口的注意事…

请相信总有一扇门为你而开——社科院与杜兰大学金融管理硕士项目

考研人数每年都在递增,考研的竞争压力也逐年增长。考研话题也备受人们关注,初试,国家线,复试,考研的每一个关卡都会冲上热搜,引发热议。国家线公布后,有人欢喜有人忧。祝福成功上岸的学子们&…

【Leetcode——排序的循环链表】

😊😊😊 文章目录一、力扣题之排序循环链表二、解题思路1. 使用双指针法2、找出最大节点,最大节点的下一个节点是最小节点,由此展开讨论总结一、力扣题之排序循环链表 题目如下:航班直达!&#…

有什么比较好的bug管理工具?5款热门工具推荐

工具再优秀,适合自己才最重要。 为尽量讲透这个问题,本文的行文结构我先整理如下: 1、为什么需要bug管理工具? 2、好的bug管理工具的标准是什么? 3、好的bug管理工具推荐(5款) 4、如何挑选适合…

雪花算法(SnowFlake)

简介现在的服务基本是分布式、微服务形式的,而且大数据量也导致分库分表的产生,对于水平分表就需要保证表中 id 的全局唯一性。对于 MySQL 而言,一个表中的主键 id 一般使用自增的方式,但是如果进行水平分表之后,多个表…

【python实操】用python写软件弹窗

文章目录前言组件label 与 多行文本复选框组件Radiobutton单选组件Frame框架组件labelframe标签框架列表框Listboxscrollbar滚动条组件scale刻度条组件spinbox组件Toplevel子窗体组件PanedWindow组件Menu下拉菜单弹出菜单总结针对组件前言 python学习之路任重而道远&#xff0…

chatgpt这么火?前端如何实现类似chatgpt的对话页面

📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者😜📝 个人主页:馆主阿牛🔥🎉 支持我:点赞👍收藏⭐️留言📝…

代码看不懂?ChatGPT 帮你解释,详细到爆!

偷个懒,用ChatGPT 帮我写段生物信息代码如果 ChatGPT 给出的的代码不太完善,如何请他一步步改好?网上看到一段代码,不知道是什么含义?输入 ChatGPT 帮我们解释下。生信宝典 1: 下面是一段 Linux 代码,请帮…

Linux命令之nano命令

一、nano命令简介 nano是一个小型、免费、友好的编辑器,旨在取代非免费Pine包中的默认编辑器Pico。nano不仅复制了Pico的外观,还实现了Pico中一些缺失(或默认禁用)的功能,例如“搜索和替换”和“转到行号和列号”。nan…

【面试题】如何避免使用过多的 if else?

大厂面试题分享 面试题库前后端面试题库 (面试必备) 推荐:★★★★★地址:前端面试题库一、引言相信大家听说过回调地狱——回调函数层层嵌套,极大降低代码可读性。其实,if-else层层嵌套,如下图…

iOS-砸壳篇(两种砸壳方式)

CrackerXI砸壳呢,当时你要是使用 frida-ios-dump 也是可以的; https://github.com/AloneMonkey/frida-ios-dump frida-ios-dump: 代码中需要更改的:手机中的内网ip 密码 等 最后放到我的砸壳路径里: python dump.py -l查看应用…
最新文章