github地址:
写在前面的话
"""读书的时候上过《设计模式》这一门课,当时使用的教材是程杰老师的《大话设计模式》,使用的语言是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:16input a operater(+ - * /):*input a number:232
点评
- 变量命名不规范
- 无用的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:12input a operater(+ - * /):/input a number:0With 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.resultnumber_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:12input a operater(+ - * /):+input a number:1224
点评
- 仅仅用到了封装, 还没用到继承和多态。
紧耦合?松耦合?
如果要支持一个开根号运算,上边的代码需要改动包括加减乘除在内的get_result
函数,应该将加减乘除运算分离, 修改其中一个不影响其他的几个。那么就需要定义一个Operator基类, 将get_result
定义为虚函数,然后通过继承和多态,分别实现加减乘除四个子类,每个子类中定义虚函数的实现逻辑。
参考资料:
改进版本3.0——简单工厂模式
from abc import ABCMeta, abstractmethodclass 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:12input a operater(+ - * /):-input a number:120
点评
- 业务逻辑与界面逻辑隔离,不关心是控制台程序还是GUI程序
- 不同运算逻辑隔离,一个运算符的增删改操作不会影响其他运算
- 面向对象思想的封装,继承,多态都有所体现
- 易维护,易扩展,易复用