[Python设计模式] 第1章 计算器——简单工厂模式
github地址:https://github.com/cheesezh/python_design_patterns
写在前面的话
"""
读书的时候上过《设计模式》这一门课,当时使用的教材是程杰老师的《大话设计模式》,使用的语言是C#,学过课程之后初期深感面向对象思想的伟大,但是很少应用到实际开发中。后来我接触了Python,现在工作中用到最多的也是Python,或许是因为Python的便利性,我写的很多脚本/程序都还是面向过程编程,缺少面向对象的思想在里边。因此,我打算重读程杰老师的《大话设计模式》并用Python进行实践。
""" by ZH奶酪——张贺
题目
用一种面向对象语言实现一个计算器控制台程序, 要求输入两个数和运算符号(+-*/), 得到结果.
基础版本
a = int(input("input a number:"))
b = str(input("input a operater(+ - * /):"))
c = int(input("input a number:"))
if b == "+":
print(a+c)
elif b == "-":
print(a-c)
elif b == "*":
print(a*c)
else b == "/":
print(a/c)
input a number:16
input a operater(+ - * /):*
input a number:2
32
点评
- 变量命名不规范
- 无用的if条件判断太多
- 除法运算中未考虑第二个数字为0的情况
改进版本1.0——规范代码
number_a = int(input("input a number:"))
operator = str(input("input a operater(+ - * /):"))
number_b = int(input("input a number:"))
if operator == "+":
print(number_a + number_b)
elif operator == "-":
print(number_a - number_b)
elif operator == "*":
print(number_a * number_b)
elif operator == "/":
if number_b != 0:
print(number_a / number_b)
else:
print("With operator '/', the second number can not be zero.")
else:
print("Wrong operator.")
input a number:12
input a operater(+ - * /):/
input a number:0
With operator '/', the second number can not be zero.
点评
- 没有使用面向对象的思想
- 只满足当前需求, 不易维护, 不易扩展, 不易复用, 不够灵活
为什么活字印刷术能位列四大发明?主要是其方法的思想。
- 文章改字方便, 可维护
- 一个字可以重复使用, 可复用
- 文章加字容易, 可扩展
- 文章改版只需移动活字, 灵活性好
复制?复用?
如果做一个带图形化界面的计算器,上边的代码需要再写一次。为了避免这样,需要将业务逻辑与界面逻辑分开,降低耦合度。
改进版本2.0——利用封装解耦
class Operation():
def __init__(self):
self.result = None
def get_result(self, number_a, number_b, operator):
if operator == "+":
self.result = number_a + number_b
elif operator == "-":
self.result = number_a - number_b
elif operator == "*":
self.result = number_a * number_b
elif operator == "/":
if number_b != 0:
self.result = number_a / number_b
else:
print("With operator '/', the second number can not be zero.")
else:
print("Wrong operator.")
return self.result
number_a = int(input("input a number:"))
operator = str(input("input a operater(+ - * /):"))
number_b = int(input("input a number:"))
operation = Operation()
print(operation.get_result(number_a, number_b, operator))
input a number:12
input a operater(+ - * /):+
input a number:12
24
点评
- 仅仅用到了封装, 还没用到继承和多态。
紧耦合?松耦合?
如果要支持一个开根号运算,上边的代码需要改动包括加减乘除在内的get_result函数,应该将加减乘除运算分离, 修改其中一个不影响其他的几个。那么就需要定义一个Operator基类, 将get_result定义为虚函数,然后通过继承和多态,分别实现加减乘除四个子类,每个子类中定义虚函数的实现逻辑。
参考资料: Python中的多态与虚函数
改进版本3.0——简单工厂模式
from abc import ABCMeta, abstractmethod
class Operation():
__metaclass__ = ABCMeta
def __init__(self):
self.result = None
@abstractmethod
def get_result(self):
pass
class AddOperation(Operation):
def get_result(self, number_a, number_b):
self.result = number_a + number_b
return self.result
class SubOperation(Operation):
def get_result(self, number_a, number_b):
self.result = number_a - number_b
return self.result
class MulOperation(Operation):
def get_result(self, number_a, number_b):
self.result = number_a * number_b
return self.result
class DivOperation(Operation):
def get_result(self, number_a, number_b):
if number_b == 0:
print("With operator '/', the second number can not be zero.")
return self.result
self.result = number_a / number_b
return self.result
如何实例化?——简单工厂模式
现在加减乘除的实现逻辑已经进一步隔离,之后即使增加一个开根号运算符,也和加减乘除无关。那么如何去实例化这些类呢?可以用简单工厂模式。
class OperationFactory():
@classmethod
def create_operate(self, operator):
oper = None
if operator == "+":
oper = AddOperation()
elif operator == "-":
oper = SubOperation()
elif operator == "*":
oper = MulOperation()
elif operator == "/":
oper = DivOperation()
else:
print("Wrong operator.")
return oper
通过上边的简单工厂,输入运算符号,就可以实例化出对应的对象。下边是客户端的代码。
number_a = int(input("input a number:"))
operator = str(input("input a operater(+ - * /):"))
number_b = int(input("input a number:"))
oper = OperationFactory.create_operate(operator)
print(oper.get_result(number_a, number_b))
input a number:12
input a operater(+ - * /):-
input a number:12
0
点评
- 业务逻辑与界面逻辑隔离,不关心是控制台程序还是GUI程序
- 不同运算逻辑隔离,一个运算符的增删改操作不会影响其他运算
- 面向对象思想的封装,继承,多态都有所体现
- 易维护,易扩展,易复用
[Python设计模式] 第1章 计算器——简单工厂模式的更多相关文章
- PYTHON设计模式,创建型之简单工厂模式
这个系统,感觉思路清爽,,相信多练练,多思考,就会熟悉的.. http://www.jianshu.com/p/2450b785c329 #!/usr/bin/evn python #coding:u ...
- [Python设计模式] 第8章 学习雷锋好榜样——工厂方法模式
github地址:https://github.com/cheesezh/python_design_patterns 简单工厂模式 v.s. 工厂方法模式 以简单计算器为例,对比一下简单工厂模式和工 ...
- 学习设计模式第二十七 - GoF之外简单工厂模式
示例代码来自<深入浅出设计模式>和<大话设计模式> 概述 简单工厂模式又被称为静态工厂模式,属于类的创建型模式.其实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品 ...
- Java 设计模式系列(二)简单工厂模式和工厂方法模式
Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...
- Javascript设计模式理论与实战:简单工厂模式
通常我们创建对象最常规的方法就是使用new关键字调用构造函数,这会导致对象之间的依赖性.工厂模式是一种有助于消除类之间依赖性的设计模式,它使用一个方法来决定要实例化哪一个类.本文详细介绍了简单工厂模式 ...
- 设计模式(C#)——02简单工厂模式
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来.通俗来说,你只关心怎么用,不用关心怎么做 ...
- 设计模式(Java语言)- 简单工厂模式
简单工厂模式有称为静态工厂模式,属于设计模式中的创建型模式.简单工厂模式通过对外提供一个静态方法来统一为类创建实例.简单工厂模式的目的是实现类与类之间解耦,其次是客户端不需要知道这个对象是如何被穿创建 ...
- 设计模式(二)——Java简单工厂模式
简单工厂模式 案例: 披萨的项目(要便于披萨种类的扩展,要便于维护) 1)披萨的种类很多(比如 GreekPizz.CheesePizz 等) 2)披萨的制作有 prepare,bake, cut, ...
- [Python设计模式] 第19章 分公司=部门?——组合模式
github地址:https://github.com/cheesezh/python_design_patterns 组合模式 组合模式,将对象组合成树形结构以表示"部分-整体" ...
随机推荐
- hdu3193 降维+rmq
/* 给定n个数对(p,d),如果有这么一个数对(pi,di),其他所有的数对都不能严格小于这个数对 请求出有多少个这样的数对! 解法:对于数对(p,d),能找到在[1,p-1]之间的小于d的数对,那 ...
- Python 检测系统时间,k8s版本,redis集群,etcd,mysql,ceph,kafka
一.概述 线上有一套k8s集群,部署了很多应用.现在需要对一些基础服务做一些常规检测,比如: 系统时间,要求:k8s的每一个节点的时间,差值上下不超过2秒 k8s版本,要求:k8s的每一个节点的版本必 ...
- java根据word模板导出word文件
1.word模板文件处理,如下图所示在word 文档中填值的地方写入占位变量 2.将word文档另存为xml文件.编辑如下图,找到填写的占位,修改为${bcrxm}格式 3.将文件后缀名改为.ftl文 ...
- Ext.js项目(一)
这个项目整体采用代码生成器生成,具体看下图:
- django的FormView中,自定义初始化表单数据的曲折方法
这个技巧,主要是用于表单初始化及回显. 也就是说,如果用户的数据库里有数据,则要将相应的数据显示在表单里, 如果用户的数据库里没有数据,才会生成一个空白的表单给用户, 这样才显得专业塞! 而我面对的尴 ...
- Servlet的多线程和线程安全
线程安全 首先说明一下对线程安全的讨论,哪种情况我们可以称作线程安全?网上对线程安全有很多描述,我比较喜欢<Java并发编程实战>给出的定义,“当多个线程访问某个类时,不管运行时环境采用何 ...
- 微信WebView关闭后本地cookie无法清除问题
问题背景 在微信WebView下的页面中登录后,关闭WebView返回后再次进入页面,发现登录态还存在,原因是微信不会主动清除cookie以及其他的缓存. 期望是关闭窗口后会清除cookie,重新进入 ...
- 【Java】 剑指offer(5) 从尾到头打印链表
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 输入一个链表的头结点,从尾到头反过来打印出每个结点的值.结点定义如下: ...
- Python String 方法详解
官网文档地址:https://docs.python.org/3/library/stdtypes.html#string-methods 官网 公号:软测小生ruancexiaosheng 文档里的 ...
- hibernate中多对一问题
例如User类中有个Group引用对应数据库就是groupId的外键了. 外键映射成一个类对吧. <many-to-one name="groupId" column=&qu ...