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. SPOJ-SERVICE 线性dp+维度压缩

    还是线性dp,有点感觉了,另外这个问题也可以用滚动数组 /* 依然是先按照阶段i划分, dp[i][j][k]表示完成第i个请求时,两个员工分别在j位置和k位置的费用(还有一个员工一定在位置p) dp ...

  2. easyUI基础入门

    头部需要引人文件:<!DOCTYPE html><html><head> <meta charset="utf-8"> <ti ...

  3. poj 2031 给出每个结点的3维坐标 以及结点的半径 (MST)

    3维空间中有N个圆球,给出x y z 以及圆球的半径 ,求最小生成树 边的权值为两个圆球间的距离 如果圆球相互接触 则权值为0 求最小的权值和 Sample Input 3 //n10.000 10. ...

  4. H 模拟水题

    n个人 小明编号为m 从编号为a的人开始数 起始数字为b 遇到素数duang 并反相 求小明应该说什么 Sample Input 310 2 //n m3 4 //a b3 32 64 13 8 Sa ...

  5. jquery数组(sort() 排序)

    HTML: <h3>字符串数组排序前</h3> <div id="show5"></div> <h3>排序后</h ...

  6. 001 Spark的简介以及入门

    1.hadoop,spark,Flink的比较 MapReduce: 分布式的计算框架 -> Hive 问题: shuffle:大文件的排序+读写磁盘+网络传输 => 比较慢 只有两种执行 ...

  7. turbo boost - 睿频加速

    turbo boost就是英特尔睿频加速技术 英特尔睿频加速技术是英特尔酷睿 i7/i5 处理器的独有特性,也是英特尔新宣布的一项技术.这项技术可以理解为自动超频.当开启睿频加速之后,CPU会根据当前 ...

  8. C语言 —— 贪吃蛇

    参考视频:https://www.bilibili.com/video/av29580072/?p=1 GreedySnake.h #ifndef GREEDYSNAKE_H_INCLUDED #de ...

  9. python获取公网ip,本地ip及所在国家城市等相关信息收藏

    python获取公网ip的几种方式       from urllib2 import urlopen   my_ip = urlopen('http://ip.42.pl/raw').read() ...

  10. 网页图表Highcharts实践教程之认识Highcharts

    网页图表Highcharts实践教程之认识Highcharts 认识Highcharts Highcharts是国际知名的一款图表插件.它完全使用Javascript编写实现.其结构清晰,使用简单.开 ...