当前位置: 首页 > news >正文

【设计模式】工厂模式

前言

1. 单例模式(Singleton Pattern):保证一个类只有一个实例,并提供一个全局的访问点。

2. 工厂模式(Factory Pattern):定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。

3. 观察者模式(Observer Pattern):定义对象之间的一对多依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会被自动通知并更新。

4. 装饰器模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,而不会影响到其他对象。

5. 策略模式(Strategy Pattern):定义一系列的算法,将每个算法封装起来,并使它们可以相互替换。

6. 命令模式(Command Pattern):将请求封装成一个对象,从而使用户可以用不同的请求对客户进行参数化。

7. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类能够一起工作。

8. 外观模式(Facade Pattern):为子系统中的一组接口提供一个统一的接口,从而使得子系统更加容易使用。

9. 状态模式(State Pattern):允许一个对象在其内部状态改变时改变其行为。

10. 模板方法模式(Template Method Pattern):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中实现。

这些是Python中常用的设计模式,通过使用这些设计模式可以提高代码的可读性、可维护性和重用性。

工厂模式(Factory Pattern)是 程序设计中 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式 中,我们在创建对象时不会对客户端暴露创建逻辑,所谓的“创建逻辑”是指我必须要知道创建函数的构造函数的逻辑组成,才能创建对象

简单工厂模式

隐藏创建类代码逻辑

import math#定义4个图形类,并且每一个图形都有一个可以计算面积的方法
class Circle:def Area(self,radius):return math.pow(radius,2)*math.piclass Rectangle:def Area(self,longth,width):return 2*longth*widthclass Triangle:def Area(self,baselong,height):return baselong*height/2class Ellipse:def Area(self,long_a,short_b):return long_a*short_b*math.pi#=================================
#定义创建对象的一个工厂
class Factory:def create_shape(self, name):if name =='Circle':return Circle()elif name == 'Rectangle':return Rectangle()elif name == 'Triangle':return Triangle()elif name == 'Ellipse':return Ellipse()else:return Noneif __name__=='__main__':factory=Factory()circle=factory.create_shape('Circle')circle_area=circle.Area(2)print(f'这是一个圆,它的面积是:{circle_area}')rectangle=factory.create_shape('Rectangle')rectangle_area=rectangle.Area(2,3)print(f'这是一个长方形,它的面积是:{rectangle_area}')triangle=factory.create_shape('Triangle')triangle_area=triangle.Area(2,3)print(f'这是一个三角形,它的面积是:{triangle_area}')ellipse=factory.create_shape('Ellipse')ellipse_area=ellipse.Area(3,2)print(f'这是一个椭圆,它的面积是:{ellipse_area}')

问题所在:不符合软件设计的开放-封闭原则,对扩展开放对修改关闭。扩展一个类的创建时,需要修改Factory类,增加if-else代码。

 解决方法:定义一个创建工厂的接口(python中通过类的继承来实现),将所有的类创建的实现单独拎出来并继承抽象工厂类(接口),实现抽象类中的创建类的方法,不放在一起。这样有新的类需要扩展时,就可以直接创建一个新的工厂类,里面实现实例化逻辑,不必修改原有的代码,最后是增加具体类并实现该类的一些行为方法

工厂模式

import math#定义4个图形类,并且每一个图形都有一个可以计算面积的方法
class Circle:def Area(self,radius):return math.pow(radius,2)*math.piclass Rectangle:def Area(self,longth,width):return 2*longth*widthclass Triangle:def Area(self,baselong,height):return baselong*height/2class Ellipse:def Area(self,long_a,short_b):return long_a*short_b*math.pi#=================================
#定义创建对象的工厂接口,因为python中并没有接口的概念,所以,这里打算通过“类的继承”加以实现
class IFactory:  #模拟接口def create_shape(self):  #定义接口的方法,只提供方法的声明,不提供方法的具体实现passclass CircleFactory(IFactory): #模拟类型实现某一个接口,实际上是类的继承def create_shape(self, name):  #重写接口中的方法if name =='Circle':return Circle()class RectangleFactory(IFactory): #模拟类型实现某一个接口,实际上是类的继承def create_shape(self, name):  #重写接口中的方法if name =='Rectangle':return Rectangle()class TriangleFactory(IFactory): #模拟类型实现某一个接口,实际上是类的继承def create_shape(self, name):  #重写接口中的方法if name =='Triangle':return Triangle()class EllipseFactory(IFactory): #模拟类型实现某一个接口,实际上是类的继承def create_shape(self, name):  #重写接口中的方法if name =='Ellipse':return Ellipse()if __name__=='__main__':factory1=CircleFactory()factory2=RectangleFactory()factory3=TriangleFactory()factory4=EllipseFactory()circle=factory1.create_shape('Circle')circle_area=circle.Area(2)print(f'这是一个圆,它的面积是:{circle_area}')rectangle=factory2.create_shape('Rectangle')rectangle_area=rectangle.Area(2,3)print(f'这是一个长方形,它的面积是:{rectangle_area}')triangle=factory3.create_shape('Triangle')triangle_area=triangle.Area(2,3)print(f'这是一个三角形,它的面积是:{triangle_area}')ellipse=factory4.create_shape('Ellipse')ellipse_area=ellipse.Area(3,2)print(f'这是一个椭圆,它的面积是:{ellipse_area}')

也有缺点

在增加新的一个类型时,也必须增加相应的新的工厂类,会带来额外的开销,会导致很多的工厂类,影响代码的简洁性。

应用场景

 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。

2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。

3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
 

参考链接:

HEADFIRST设计模式

 Python 抽象工厂模式讲解和代码示例

一文详解“工厂方法模式”以及python语言的实现_python 工厂方法模式-CSDN博客

一文详解“工厂模式”以及python语言的实现-CSDN博客

相关文章:

  • 【动态规划】C++算法:446等差数列划分 II - 子序列
  • 带前后端H5即时通讯聊天系统源码
  • ES-极客学习第二部分ES 入门
  • 二叉树的层序遍历经典问题(算法村第六关白银挑战)
  • 缓存cache和缓冲buffer的区别
  • 3.3 设计模式基础
  • 机器学习 前馈神经网络
  • 芯片命名大全:完整的器件型号包括主体型号、前缀、后缀等!
  • Unity之预制体与变体
  • 【Leetcode】242.有效的字母异位词
  • Spring Boot中加@Async和不加@Async有什么区别?设置核心线程数、设置最大线程数、设置队列容量是什么意思?
  • 申请域名SSL证书并自动推送至阿里云 CDN
  • Linux Lha命令教程:学习如何管理.lzh文件(附案例详解和注意事项)
  • Qt实现简单的分割窗口
  • 站长工具之PHP单文件实现IP归属地批量查询
  • 【EOS】Cleos基础
  • Docker下部署自己的LNMP工作环境
  • Go 语言编译器的 //go: 详解
  • JavaScript设计模式之工厂模式
  • jquery ajax学习笔记
  • Laravel核心解读--Facades
  • mongodb--安装和初步使用教程
  • October CMS - 快速入门 9 Images And Galleries
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SpiderData 2019年2月16日 DApp数据排行榜
  • underscore源码剖析之整体架构
  • Vue2 SSR 的优化之旅
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 产品三维模型在线预览
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 算法系列——算法入门之递归分而治之思想的实现
  • 跳前端坑前,先看看这个!!
  • 微服务入门【系列视频课程】
  • 再次简单明了总结flex布局,一看就懂...
  • 在electron中实现跨域请求,无需更改服务器端设置
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​第20课 在Android Native开发中加入新的C++类
  • ​业务双活的数据切换思路设计(下)
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (33)STM32——485实验笔记
  • (4.10~4.16)
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (算法)Travel Information Center
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (译)2019年前端性能优化清单 — 下篇
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NET 中什么样的类是可使用 await 异步等待的?