switch (aRental.movie.priceCode) { case .Regular: result += 2 if (aRental.daysRented > 2) { result += (Double)(aRental.daysRented - 2) * 1.5 } case .NewRelease: result += (Double)(aRental.daysRented) * 3.0 case .Children : result += 1.5 if (aRental.daysRented > 3) { result += (Double)(aRental.daysRented - 3) * 1.5 } } return result }
而对应的在statement()中的使用部分是:
//Customer for rental in rentals { let thisAmount: Double = amountForEach(rental)
//Rental var charge: Double { get { var result: Double = 0
switch (movie.priceCode) { case .Regular: result += 2 if (daysRented > 2) { result += (Double)(daysRented - 2) * 1.5 } case .NewRelease: result += (Double)(daysRented) * 3.0 case .Children : result += 1.5 if (daysRented > 3) { result += (Double)(daysRented - 3) * 1.5 } } return result } }
//Rental var frequentRenterPoints : Double { get { if movie.priceCode == .NewRelease && daysRented > 1 { return2 } return1 } }
而对应的statement()也相应的被简化了:
//Customer funcstatement() -> String {
var totalAmount: Double = 0 var frequentRenterPoints:Double = 0
var result: String = "Rental Record for \(name) \n"
for rental in rentals {
frequentRenterPoints += rental.frequentRenterPoints result += "\t \(rental.movie.title) \t \(rental.charge) \n" totalAmount += rental.charge } result += "Amount owned is \(totalAmount) \n" result += "You earned \(frequentRenterPoints) frequent renter points" return result }
去除临时变量
正如前面提到的,临时变量可能是个问题。这里还有两个临时变量:totalAmount和frequentRenterPoints,两者都是用来从Customer中的Rental对象中获取某个总量,不论是statement()还是HTMLStatemnet()都会使用到它们,所以继续利用Replace Temp with Query来替代这两个临时变量。
//Cunstomer private var totalCharge: Double { get { var result: Double = 0 for rental in rentals { result += rental.charge } return result } }
private var totalFrequentRenterPoints: Double { get { var result: Double = 0 for rental in rentals { result += rental.frequentRenterPoints } return result } }
funcstatement() -> String { var result: String = "Rental Record for \(name) \n"
for rental in rentals {
result += "\t \(rental.movie.title) \t \(rental.charge) \n" }
result += "Amount owned is \(totalCharge) \n" result += "You earned \(totalFrequentRenterPoints) frequent renter points"
return result }
到现在,我们终于可以戴上添加新功能的帽子,增加HTMLStatment()
//Customer funcHTMLStatement() -> String { var result: String = "<h1>Rentals for <em>\(name)</em></h1><p>\n" for rental in rentals { result += "\(rental.movie.title): \(rental.charge) <br>\n" }
result += "<p>You owe <em>\(totalCharge) </em><p>\n" result += "On this rental you earned <em>\(totalFrequentRenterPoints)</em> frequent renter points<p>"
funcgetCharge(DaysRented daysRented: Int) -> Double{ var result: Double = 0 switch(priceCode) { case .Children: result += 1.5 if (daysRented > 3) { result += (Double)(daysRented - 3) * 1.5 } case .Regular: result += 2 if (daysRented > 2) { result += (Double)(daysRented - 2) * 1.5; } case .NewRelease: result += Double(daysRented) * 3.0 } return result }
首先要使用Replace Type Code with State/Strategy,第一步是针对类型代码使用Self Encapsulate Field来确保通过getter和setter来访问类型代码。也就是priceCode属性需要通过getter和setter来使用,这样的属性在Swift里叫做computed property,与之相对应的是stored property。在这里把priceCode作为了计算属性,而新增加一个存储属性是遵守’Price’协议的price属性:
//Movie var priceCode: MovieType {
get { return price.priceCode }
set { switch (newValue) { case .Regular: price = RegularPrice() case .Children: price = ChildrenPrice() case .NewRelease: price = NewReleasePrice() } } } var price: Price!