前幾個Kata基本上是為了練習而練習,猜測作者的目的是鍛煉讀者抽象和重構的意識。思維訓練過后,這個Kata又要結合具體場景進行實戰了。
還記得第一個Kata嗎?在第一個Kata中我們不需要寫代碼,只是通過思考提出了一個定價模型,而這個Kata的要求正是實現Kata01中的部分策略。
假設有如下定價策略:
商品 單價 特價
--------------------------
A 50 3 個 130
B 30 2 個 45
C 20
D 15
需要實現收款機模型,讀入購買物品,輸出總價。
思路
乍一看挺簡單的,不斷讀入商品,如果發現有商品滿足特價條件就應用特價,最終結算總價。不過有幾個細節需要思考。
如何抽象特價規則
題目中的特價規則很簡單,每條規則只涉及一件商品,那如果涉及多個商品如何處理?
如何應用特價
應用特價時對特價商品進行標記還是直接把特價商品和普通商品存儲在不同類別中?
如何計算總價
每次讀入商品處理完之后更新總價?還是動態計算價格?
我的選擇請看代碼。
代碼
class PriceCalculator:
def __init__(self, prices, rules):
self.prices = prices
self.rules = rules
self.special = {} # 特價商品和普通商品分開存儲
self.normal = {}
def add(self, good):
for i in good:
self.normal.setdefault(i, 0)
self.normal[i] += 1
self.checkRules()
def checkRules(self):
hasChange = True
while hasChange:
hasChange = False
for index, rule in self.rules.iteritems():
satisfied = True
for good in rule['good']:
if not (good in self.normal and self.normal[good] >= rule['good'][good]):
satisfied = False
break
if satisfied:
hasChange = True
self.special.setdefault(index, 0)
self.special[index] += 1
for good in rule['good']:
self.normal[good] -= rule['good'][good]
def getPrice(self): # 動態計算價格
totalPrice = 0
for index, count in self.special.iteritems():
totalPrice += self.rules[index]['price'] * count
for good, count in self.normal.iteritems():
totalPrice += self.prices[good] * count
return totalPrice
prices = {'A': 50, 'B': 30, 'C': 20, 'D': 15}
rules = {
0: {'good': {'A': 3}, 'price': 130}, # 規則可以包含不同數量的不同商品
1: {'good': {'B': 2}, 'price': 45}
}
cal = PriceCalculator(prices, rules)
cal.add('AAAAAA')
print cal.getPrice()
上面的三個問題都在注釋中標出了我的解決方案,具體的細節請閱讀代碼。
可以通過add方法多次輸入商品,我這里只讀入了一次,其實是支持多次的。
總結
我的模型有點過于簡單,如果把商品抽象為另一個class應該會更合適一些,不過總體的邏輯并沒有區別。
特價規則現在可以滿足滿減的情況,但是并不能滿足買贈,可以進一步把規則抽象成兩部分:條件和優惠,從而滿足多種規則。