原文是JS代码写的,我试图用Python改写,第一章上半部分的内容可以参考:
第一章下半部分的内容包括了很多多态重构的内容,因此单独拉出来一个帖子。
JS的代码和Python的实现形式在很多处还是有一些不同,在阅读的时候不要过于关注代码的形式,要尝试去解读背后的内容。
我会在代码中加入一部分注释用于解释其意图,我觉得已经很清晰了。如果以后有多余的时间,我还会加入流程图来对程序进行说明。
import math
# 定义数据源的结构
class play(object):
def __init__(self, name_, type_):
self.name = name_
self.type = type_
class plays_class(object):
def __init__(self):
self.hamlet = play('Hamlet', 'tragedy')
self.as_like = play('As You Like It', 'comedy')
self.othello = play('Othello', 'tragedy')
class performance(object):
def __init__(self, playID, audience):
self.playID = playID
self.audience = audience
class invoices_class(object):
def __init__(self):
self.customer = 'BigCo'
self.performances = [
performance('hamlet', 55),
performance('as_like', 35),
performance('othello', 40)
]
# 格式转换
def usd(num):
return '$%.2f' % num
# 文本生成器,通过接收createstatementdata()返回的数据来生成文本
def renderplaintext(data):
result = f'Statement for {data.customer}\n'
for perf in data.performances:
result += f' {perf.play.name}: {usd(perf.amount / 100)} ({perf.audience} seats) \n'
result += f'Amount owned is {usd(data.totalamount / 100)} \n'
result += f'You earned {data.totalvolumecredits} credits\n'
return result
# 数据生成器,用于计算需要输出的数据
def createstatementdata(invoice, plays):
class result(object):
pass
result.customer = invoice.customer
result.performances = list(map(enrichPerformance, invoice.performances))
result.totalamount = totalamount(result)
result.totalvolumecredits = totalvolumecredits(result)
return renderplaintext(result)
def enrichPerformance(aPerformance):
calculator = createPerformanceCalculator(aPerformance, playfor(aPerformance))
result = aPerformance
result.play = calculator.play
result.amount = calculator.amount
result.volumeCredits = calculator.volumecredits
return result
# 以查询取代参数
def playfor(aPerformance):
return plays.__getattribute__(aPerformance.playID)
def totalamount(data):
result = 0
for perf in data.performances:
thisamount = 0
result += amountfor(perf)
return result
def totalvolumecredits(data):
result = 0
for perf in data.performances:
result += volumecreditsfor(perf)
return result
# 子类分流器,以多态取代条件语句
def createPerformanceCalculator(aPerformance, aPlay):
switch_dict = dict(
tragedy=TragedyCalculator(aPerformance, aPlay),
comedy=ComedyCalculator(aPerformance, aPlay)
)
return switch_dict.get(aPlay.type)
# 父类,负责更通用的逻辑部分
class PerformanceCalculator(object):
def __init__(self, aPerformance, aPlay):
self.performance = aPerformance
self.play = aPlay
@property
def volumecredits(self):
return max(self.performance.audience - 30, 0)
class TragedyCalculator(PerformanceCalculator):
@property
def amount(self):
result = 40000
if self.performance.audience > 30:
result += 1000 * (self.performance.audience - 30)
return result
pass
class ComedyCalculator(PerformanceCalculator):
@property
def amount(self):
result = 30000
if self.performance.audience > 20:
result += 10000 + 500 * (self.performance.audience - 20)
result += 300 * self.performance.audience
return result
@property
def volumecredits(self):
return super().volumecredits + math.floor(self.performance.audience / 5)
pass
def amountfor(aPerformance):
return createPerformanceCalculator(aPerformance, playfor(aPerformance)).amount
# 此部分的条件语句if被多态取代条件语句给分流了,分别放入了父类PerformanceCalculator和子类ComedyCalculator中
# def volumecreditsfor(aPerformance):
# result = 0
# result += max(aPerformance.audience - 30, 0)
# # add extra credit for every ten comedy attendees
# if 'comedy' == playfor(aPerformance).type:
# result += math.floor(aPerformance.audience / 5)
# return result
if __name__ == '__main__':
plays = plays_class()
invoices = invoices_class()
print(createstatementdata(invoices, plays))
“互联网精神”即:开放、平等、协作、快速、分享
对更多内容感兴趣欢迎关注我的个人公众号:梧承 Book House