原文取自大话设计模式,不同之处在于原文是基于C#编写的,我在这里用Python表述
需求:使用python语言开发实现2个数相加减及扩展的计算器
初学者代码如下:
if __name__ == "__main__":
print("请输入数字A:")
a = input()
print("请输入数字B:")
b = input()
print("请输入运算符:")
c = input()
if (c == "+"):
print(int(a) + int(b))
elif (c == "-"):
print(a - b)
elif (c == "*"):
print(a * b)
else:
print(a / b)
注意,Python无法使用switch语句。
上述代码的缺点,如果要添加其他运算方式或修改已有的运算方式,那么每次修改都要在上述的elif语句里面添加新的条件或修改已有的代码,完全不具备扩展性和维护性。(哪怕将上述的非核心代码封装到某个方法中,依然如此)
对上述代码进行修改:
首先引入包:
import abc
然后提取上述需求中不改变的东西为基类:
这里定义a,b为operation类的两个类变量
# 定义运算类
# python的抽象方法必须含有至少一个参数,默认使用self函数
# 子类使用父类变量是,必须通过self对象、等同于this
class operation():
a = 0
b = 0
@abc.abstractmethod
def getResult(self):
pass
定义一个获取结果的getResult方法,且该方法是抽象方法。
使用@abc.abstractmethod声明的方法为抽象方法,该方法需要其继承类重新改写
然后定义上述基类的实现类(主要是实现上述类的抽象方法),即对基类进行扩展改造:
# 运算类的实现类-加运算
class operationAdd(operation):
def getResult(self):
print(int(self.a) + int(self.b))
# 运算类的实现类-减运算
class operationSub(operation):
def getResult(self):
print(int(self.a) - int(self.b))
# #############################
# 可以继续添加其他运算类的实现类
# #############################
定义运算工厂类,用来获取实现类:
# 运算工厂类
class operationFactory():
# 运算类的静态方法
@staticmethod
def createOperation(operation):
opera = None
# 这里可以添加其他运算方法
if (operation == "+"):
opera = operationAdd()
elif (operation == "-"):
opera = operationSub()
elif (operation == "*"):
pass
else:
pass
return opera
最后就是主函数:
if __name__ == "__main__":
print("请输入数字A:")
a = input()
print("请输入数字B:")
b = input()
print("请输入运算符:")
c = input()
opera = operationFactory.createOperation(c)
opera.a = a
opera.b = b
opera.getResult()
在主函数中,operationFactory.createOperation方法可以根据你的输入,获取指定的运算对象。
然后通过指定的运算对象,调用其getResult()方法就可以获取该类特有的运算结果。
优点:无论添加多少新的运算方式,只要使其重写基类的抽象函数,再在工厂类中添加相应的分支代码,就可以获取该类的特有运算结果。
缺点:添加新的运算类需要修改工厂方法,每次添加,工厂类都要重新打包编译。
总结:
#一个实体类(包含抽象方法),实体类的实现类 (扩展类)
# 一个工厂类(用来根据不同需求实例化不同实现类)、
# 一个主函数
# 即通过工厂类获取【基类的实现类】,然后调用【基类的实现类】的特定抽象方法,获取对应结果
编码中的小发现:
# 说起来python的类变量、突然想起来ptyhon中是否含有类的静态变量这个东西。
# 然后就敲了下面的代码使其和C#代码进行对比。
# 对比发现,python和C#的一点点不同,python类里面定义的变量,如果通过类名去改变,则所有的实例对象的变量都会受到影响。
# class demo():
# a=10
# if __name__ == "__main__":
# demoB = demo()
# demoB.a = 1
# demo.a = 100
# demoA = demo()
# demoB = demo()
# print(demoA.a, demoB.a)
# 这里输出100,100
# if __name__ == "__main__":
#
# demoA=demo()
# demoA.a=100
# demoB=demo()
# print(demoA.a,demoB.a)
# 这里输出100,10
不对之处敬请指正!