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

点评

  1. 变量命名不规范
  2. 无用的if条件判断太多
  3. 除法运算中未考虑第二个数字为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.

点评

  1. 没有使用面向对象的思想
  2. 只满足当前需求, 不易维护, 不易扩展, 不易复用, 不够灵活

为什么活字印刷术能位列四大发明?主要是其方法的思想。

  1. 文章改字方便, 可维护
  2. 一个字可以重复使用, 可复用
  3. 文章加字容易, 可扩展
  4. 文章改版只需移动活字, 灵活性好

复制?复用?

如果做一个带图形化界面的计算器,上边的代码需要再写一次。为了避免这样,需要将业务逻辑与界面逻辑分开,降低耦合度。

改进版本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

点评

  1. 仅仅用到了封装, 还没用到继承和多态。

紧耦合?松耦合?

如果要支持一个开根号运算,上边的代码需要改动包括加减乘除在内的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

点评

  1. 业务逻辑与界面逻辑隔离,不关心是控制台程序还是GUI程序
  2. 不同运算逻辑隔离,一个运算符的增删改操作不会影响其他运算
  3. 面向对象思想的封装,继承,多态都有所体现
  4. 易维护,易扩展,易复用

[Python设计模式] 第1章 计算器——简单工厂模式的更多相关文章

  1. PYTHON设计模式,创建型之简单工厂模式

    这个系统,感觉思路清爽,,相信多练练,多思考,就会熟悉的.. http://www.jianshu.com/p/2450b785c329 #!/usr/bin/evn python #coding:u ...

  2. [Python设计模式] 第8章 学习雷锋好榜样——工厂方法模式

    github地址:https://github.com/cheesezh/python_design_patterns 简单工厂模式 v.s. 工厂方法模式 以简单计算器为例,对比一下简单工厂模式和工 ...

  3. 学习设计模式第二十七 - GoF之外简单工厂模式

    示例代码来自<深入浅出设计模式>和<大话设计模式> 概述 简单工厂模式又被称为静态工厂模式,属于类的创建型模式.其实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品 ...

  4. Java 设计模式系列(二)简单工厂模式和工厂方法模式

    Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...

  5. Javascript设计模式理论与实战:简单工厂模式

    通常我们创建对象最常规的方法就是使用new关键字调用构造函数,这会导致对象之间的依赖性.工厂模式是一种有助于消除类之间依赖性的设计模式,它使用一个方法来决定要实例化哪一个类.本文详细介绍了简单工厂模式 ...

  6. 设计模式(C#)——02简单工厂模式

    推荐阅读:  我的CSDN  我的博客园  QQ群:704621321       工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来.通俗来说,你只关心怎么用,不用关心怎么做 ...

  7. 设计模式(Java语言)- 简单工厂模式

    简单工厂模式有称为静态工厂模式,属于设计模式中的创建型模式.简单工厂模式通过对外提供一个静态方法来统一为类创建实例.简单工厂模式的目的是实现类与类之间解耦,其次是客户端不需要知道这个对象是如何被穿创建 ...

  8. 设计模式(二)——Java简单工厂模式

    简单工厂模式 案例: 披萨的项目(要便于披萨种类的扩展,要便于维护) 1)披萨的种类很多(比如 GreekPizz.CheesePizz 等) 2)披萨的制作有 prepare,bake, cut, ...

  9. [Python设计模式] 第19章 分公司=部门?——组合模式

    github地址:https://github.com/cheesezh/python_design_patterns 组合模式 组合模式,将对象组合成树形结构以表示"部分-整体" ...

随机推荐

  1. hdu 1588 求f(b) +f(k+b) +f(2k+b) +f((n-1)k +b) 之和 (矩阵快速幂)

    g(i)=k*i+b; 0<=i<nf(0)=0f(1)=1f(n)=f(n-1)+f(n-2) (n>=2)求f(b) +f(k+b) +f(2*k+b) +f((n-1)*k + ...

  2. openstack安装-计算节点-neutron服务安装

    一.安装nettron相关服务 yum install openstack-neutron-linuxbridge ebtables ipset -y 二.快速配置配置  修改红色部分为计算节点的网卡 ...

  3. Python open详解

    一.打开文件的模式有: 1.r,只读模式[默认]. 2.w,只写模式.[不可读,不存在则创建,存在则删除内容] 3.a,追加模式.[可读,不存在则创建,存在则只追加内容] 二.+ 表示可以同时读写某个 ...

  4. jQuery如何退出each循环 和如何退出function函数

    1.在函数内部使用return false是跳出function; 2.在each的回调函数中使用return false,是跳出each循环;return true 进入下一个循环: 3.break ...

  5. BZOJ1260 [CQOI2007]涂色paint 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1260 题意概括 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂 ...

  6. P1865 A % B Problem 素数筛

    题目描述 区间质数个数 输入输出格式 输入格式: 一行两个整数 询问次数n,范围m 接下来n行,每行两个整数 l,r 表示区间 输出格式: 对于每次询问输出个数 t,如l或r∉[1,m]输出 Cros ...

  7. 057 Hive项目案例过程

    1.说明 这里只粘贴一张,图,主要针对的hive的项目的实践过程. 2.图 3.需求 统计PV 统计注册人数 => 这个是一个公司会关注的,每天的注册率. 统计ip 统计跳出率 => ip ...

  8. git add Untracked files

    git add *  将目录里的所有文件提交到暂存区后 git status 查看状态  所有文件都是绿色的表示本地的文件和暂存区的文件是一样的 然后在本地修改一个文件 然后新建一个文件 在使用git ...

  9. DP-hdu1176

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1176 这道题与动态规划中的数塔问题十分类似,因此如果对于数塔问题还不太明白的,可以先参考一下博客: 数 ...

  10. 字符串处理-Hdu1004

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1004 题目大意:给你一个数n,要求输入n个字符串,在这n个字符串中,我们需要输出出现次数最多的字符串. ...