python版简单工厂模式


Posted in Python onOctober 16, 2017

什么是简单工厂模式

工厂模式有一种非常形象的描述,建立对象的类就如一个工厂,而需要被建立的对象就是一个个产品;在工厂中加工产品,使用产品的人,不用在乎产品是如何生产出来的。从软件开发的角度来说,这样就有效的降低了模块之间的耦合。
简单工厂的作用是实例化对象,而不需要客户了解这个对象属于哪个具体的子类。简单工厂实例化的类具有相同的接口或者基类,在子类比较固定并不需要扩展时,可以使用简单工厂。如数据库生产工厂就是简单工厂的一个应用
采用简单工厂的优点是可以使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性;缺点是可实例化的类型在编译期间已经被确定,如果增加新类 型,则需要修改工厂,不符合OCP(开闭原则)的原则。简单工厂需要知道所有要生成的类型,当子类过多或者子类层次过多时不适合使用。

简单工厂模式实现

下面考虑《大话设计模式》中的一个例子:
题目:用任意一种面向对象语言实现一个计算器控制台程序。要求输入两个数和运算符号,得到结果。

题目分析:

程序应该做到:(1)可维护;(2)可复用;(3)可扩展;(4)灵活性好。
可维护:就是说代码一处更改,不能产生连锁反应,不能影响其他地方。
可复用:尽量减少重复性代码。
可扩展:如果要扩展新的功能、新的业务,则只需要增加新的类就好了,不对已有的类和逻辑产生影响。插拔式的应用。
面向对象要点:
面向对象三大特性:封装、继承、多态。
通过封装、继承、多态把程序耦合降低。
业务逻辑和界面逻辑分开。

类的结构图:

python版简单工厂模式

代码实现:

1. 首先,搞清楚业务中容易发生变化的部分。在本应用中,要求计算两个数的运算结果,那么要进行什么样的运算,这就是一个容易发生变化的部分。例如,我们现在只想实现加减乘除运算,后期又想增加开根或者求余运算。那么如何应对这种需求带来的变化。在程序设计的时候就应该考虑到程序的可维护性、可扩展性、代码的可复用性、灵活性等等。 

2. 例如现在这个运算器只有加减乘除四种运算。首先建一个Operation类,这个类是各种具体运算类(加减乘除)的父类,主要是接受用户输入的数值。该类如下:

class Operation(): 
  def __init__(self,NumberA=0,NumberB=0): 
    self.NumberA = NumberA 
    self.NumberB = NumberB 
 
  def GetResult(self): 
    pass

3. 然后是具体的运算类:Add、Sub、Mul、Div。他们都继承了Operation类,并且重写了getResult()方法。这样就可以用多态性降低不同业务逻辑的耦合度,修改任何一种运算类都不会影响其他的运算类。具体类的代码如下:

class AddOp(Operation): 
  def GetResult(self): 
    return self.NumberB + self.NumberA 
 
class MinusOp(Operation): 
  def GetResult(self): 
    return self.NumberA - self.NumberB 
 
class MultiOp(Operation): 
  def GetResult(self): 
    return self.NumberA * self.NumberB 
 
class DivideOp(Operation): 
  def GetResult(self): 
    try: 
      return 1.0*self.NumberA / self.NumberB 
    except ZeroDivisionError: 
      raise

4.  那么如何让计算器知道我是要用哪一种运算呢?也就是说到底要实例化哪一个具体的运算类,Add?Sub?Mul?Div?这时就应该考虑用 一个单独的类来做这个创造具体实例的过程,这个类就是工厂类。如下:

class OperationFatory(): 
  def ChooseOperation(self,op): 
    if op == '+': 
      return AddOp() 
    if op == '-': 
      return MinusOp() 
    if op == '*': 
      return MultiOp() 
    if op == '/': 
      return DivideOp()

5. 这样,用户只要输入运算符,工厂类就可以创建合适的实例,通过多态性,即返回给父类的方式实现运算结果。客户端代码如下:

if __name__ == '__main__': 
  ch = '' 
  while not ch=='q':  
    NumberA = eval(raw_input('Please input number1: ')) 
    op = str(raw_input('Please input the operation: ')) 
    NumberB = eval(raw_input('Please input number2: ')) 
    OPFactory = OperationFatory() 
    OPType = OPFactory.ChooseOperation(op) 
    OPType.NumberA = NumberA 
    OPType.NumberB = NumberB 
    print 'The result is:',OPType.GetResult() 
    print '\n#-- input q to exit any key to continue' 
    try: 
      ch = str(raw_input()) 
    except: 
      ch = ''

完整版代码如下:

# -*-coding:UTF-8-*-  
from abc import ABCMeta,abstractmethod 
 
class Operation(): 
  def __init__(self,NumberA=0,NumberB=0): 
    self.NumberA = NumberA 
    self.NumberB = NumberB 
 
  def GetResult(self): 
    pass 
 
class AddOp(Operation): 
  def GetResult(self): 
    return self.NumberB + self.NumberA 
 
class MinusOp(Operation): 
  def GetResult(self): 
    return self.NumberA - self.NumberB 
 
class MultiOp(Operation): 
  def GetResult(self): 
    return self.NumberA * self.NumberB 
 
class DivideOp(Operation): 
  def GetResult(self): 
    try: 
      return 1.0*self.NumberA / self.NumberB 
    except ZeroDivisionError: 
      raise 
 
class OperationFatory(): 
  def ChooseOperation(self,op): 
    if op == '+': 
      return AddOp() 
    if op == '-': 
      return MinusOp() 
    if op == '*': 
      return MultiOp() 
    if op == '/': 
      return DivideOp() 
 
if __name__ == '__main__': 
  ch = '' 
  while not ch=='q':  
    NumberA = eval(raw_input('Please input number1: ')) 
    op = str(raw_input('Please input the operation: ')) 
    NumberB = eval(raw_input('Please input number2: ')) 
    OPFactory = OperationFatory() 
    OPType = OPFactory.ChooseOperation(op) 
    OPType.NumberA = NumberA 
    OPType.NumberB = NumberB 
    print 'The result is:',OPType.GetResult() 
    print '\n#-- input q to exit any key to continue' 
    try: 
      ch = str(raw_input()) 
    except: 
      ch = ''

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用pyhook监控键盘并实现切换歌曲的功能
Jul 18 Python
详解Python迭代和迭代器
Mar 28 Python
详解如何利用Cython为Python代码加速
Jan 27 Python
python模拟表单提交登录图书馆
Apr 27 Python
python将字符串以utf-8格式保存在txt文件中的方法
Oct 30 Python
Python解决线性代数问题之矩阵的初等变换方法
Dec 12 Python
初探利用Python进行图文识别(OCR)
Feb 26 Python
Python的matplotlib绘图如何修改背景颜色的实现
Jul 16 Python
python系列 文件操作的代码
Oct 06 Python
python3 动态模块导入与全局变量使用实例
Dec 22 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
Feb 29 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
Mar 08 Python
Python实现扩展内置类型的方法分析
Oct 16 #Python
Python使用文件锁实现进程间同步功能【基于fcntl模块】
Oct 16 #Python
python利用paramiko连接远程服务器执行命令的方法
Oct 16 #Python
基于使用paramiko执行远程linux主机命令(详解)
Oct 16 #Python
python中文件变化监控示例(watchdog)
Oct 16 #Python
python中import reload __import__的区别详解
Oct 16 #Python
使用Python操作excel文件的实例代码
Oct 15 #Python
You might like
中国第一家无线电行
2021/03/01 无线电
使用TinyButStrong模板引擎来做WEB开发
2007/03/16 PHP
javascript some()函数用法详解
2014/11/13 PHP
yii2学习教程之5种内置行为类详解
2017/08/03 PHP
javascript中encodeURI和decodeURI方法使用介绍
2013/05/06 Javascript
JavaScript 中的日期和时间及表示标准介绍
2013/08/21 Javascript
多引号嵌套的变量命名的问题
2014/05/09 Javascript
实现图片预加载的三大方法及优缺点分析
2014/11/19 Javascript
JS实现根据文件字节数返回文件大小的方法
2016/08/02 Javascript
Bootstrap Multiselect 常用组件实现代码
2017/07/09 Javascript
面包屑导航详解
2017/12/07 Javascript
JavaScript函数式编程(Functional Programming)声明式与命令式实例分析
2019/05/21 Javascript
js实现左右轮播图
2020/01/09 Javascript
es6数组的flat(),flatMap()函数用法实例分析
2020/04/18 Javascript
微信小程序国际化探索实现(附源码地址)
2020/05/20 Javascript
[01:19]DOTA2城市挑战赛报名开始 开启你的城市传奇
2018/03/23 DOTA
浅谈python字符串方法的简单使用
2016/07/18 Python
Python无损音乐搜索引擎实现代码
2018/02/02 Python
python_opencv用线段画封闭矩形的实例
2018/12/05 Python
Python发展简史 Python来历
2019/05/14 Python
pyQt5实时刷新界面的示例
2019/06/25 Python
Python遍历字典方式就实例详解
2019/12/28 Python
opencv python图像梯度实例详解
2020/02/04 Python
使用sklearn的cross_val_score进行交叉验证实例
2020/02/28 Python
python开发一款翻译工具
2020/10/10 Python
自我鉴定范文
2013/11/10 职场文书
跟单文员的岗位职责
2013/11/14 职场文书
英语教学随笔感言
2014/02/20 职场文书
大学新生军训感言
2014/02/25 职场文书
继承权公证书
2014/04/09 职场文书
献爱心倡议书
2014/04/14 职场文书
村党支部书记四风问题个人对照检查材料思想汇报
2014/10/06 职场文书
2015年司机年终工作总结
2015/05/14 职场文书
三十年再续同学情倡议书
2019/11/27 职场文书
如何利用React实现图片识别App
2022/02/18 Javascript
Redis 限流器
2022/05/15 Redis