從一場比賽說起
在一個軟件村裏
有一名資深「面向過程」程序員——老過
和一名「面向對象」信徒——阿對
同時受僱於一家挨踢店
有一天老闆突發奇想
決定讓這兩名程序員進行一次比賽
獲勝者將獲得一個限量的
360 度全自動按摩椅
編程比賽開始了
不一會,他倆都寫出了幾乎相同的代碼
class Bill{
// 獲取總價
fun getPrice(): Double {
val unit = getUnit()
val number = getNumber()
val price = unit * number
return price
}
// 獲取單價
fun getUnit(): Double {
...
}
// 獲取數量
fun getNumber(): Int {
...
}
}
老過看到新需求,微微一笑
class Bill{
fun getPrice(): Double {
val unit = getUnit()
val number = getNumber()
val price = unit * number
if (todayIsLoversDay()) {
return price * 0.77
}
return price
}
fun getUnit(): Double {
...
}
fun getNumber(): Int {
...
}
fun todayIsLoversDay(): Boolean {
...
}
}
他決定讓新的收銀方式繼承 Bill 類
先在 Bill 類中新增 discount 方法
並將其開放
普通的收費方式在 discount
函數中直接返回價格
七夕節的收費方式則繼承此類
在 discount 函數中實現打 77折
open class Bill{
fun getPrice(): Double {
val unit = getUnit()
val number = getNumber()
val price = unit * number
return discount(price)
}
// 處理打折優惠
open fun discount(price: Double): Double{
return price
}
fun getUnit(): Double {
...
}
fun getNumber(): Int {
...
}
}
class LoversDayBill : Bill(){
override fun discount(price: Double): Double {
return price * 0.77
}
}
老過已經開始幻想自己將來
坐在按摩椅上的舒服日子
聽到新需求
老過一陣頭大
不由在羣裏吐槽
吐槽歸吐槽
老過在 getPrice 函數中
再次增加了條件判斷
class Bill {
fun getPrice(): Double {
val unit = getUnit()
val number = getNumber()
val price = unit * number
if (todayIsLoversDay()) {
return price * 0.77
}
if (todayIsMiddleAutumn() && price > 399) {
return price - 200
}
if (todayIsNationalDay() && price < 100) {
// 生成 0 ~ 9 隨機數字,如果爲 0 則免單。即:十分之一概率免單
val free = Random().nextInt(10)
if (free == 0) {
return 0.0
}
}
return price
}
fun getUnit(): Double {
...
}
fun getNumber(): Int {
...
}
fun todayIsLoversDay(): Boolean {
...
}
fun todayIsMiddleAutumn(): Boolean {
...
}
fun todayIsNationalDay(): Boolean {
...
}
}
看着越來越複雜的 Bill 類和 getPrice 方法老過眉頭緊鎖他深知事情遠沒有結束
中秋和國慶一過他還需要到這個複雜的類中刪掉打折的方法
天知道老闆還會再提什麼天馬行空的需求無論是新增或刪除代碼,在這個過長的類裏做修改都是件不太愉快的事。
爲了在一個很長的函數中找到需要修改的位置,
「面向過程」使得老過不得不瀏覽大量與修改無關的代碼,
小心翼翼地修改後,又要反覆確認不會影響到類的其他部分。
老過在心底裏默默地祈禱
這個類不再需要修改提交了自己的程序
阿對收到新需求時
先是新增了中秋節支付類
class MiddleAutumePrice : Bill() {
override fun discount(price: Double): Double {
if (price > 399) {
return price - 200
}
return super.discount(price)
}
}
再增加了國慶節支付類:
class NationalDayBill : Bill() {
override fun discount(price: Double): Double {
if (price < 100) {
// 生成 0 ~ 9 隨機數字,如果爲 0 則免單。即:十分之一概率免單
val free = Random().nextInt(10)
if (free == 0) {
return 0.0
}
}
return super.discount(price)
}
}
「面向對象」讓阿對最喜歡的一點是
有一個好消息要告訴大家!當老闆興高采烈地說出這句話時老過和阿對都露出了心驚膽戰的表情這句話往往意味着要更改需求
老過反抗道
但他並沒有說出心裏另一個小九九
實在不想再去給 Bill 類添加代碼了
這次修改老過花了較長的時間才完成
class Bill {
val gifts = listOf("flower", "chocolate", "9.9 discount")
fun getPrice(): Double {
val unit = getUnit()
val number = getNumber()
val price = unit * number
if (todayIsLoversDay() && isCouple()) {
if (price > 99) {
val lucky = Random().nextInt(gifts.size)
println("Congratulations on getting ${gifts[lucky]}!")
}
return price * 0.77
}
if (todayIsMiddleAutumn() && price > 399) {
return price - 200
}
if (todayIsNationalDay() && price < 100) {
// 生成 0 ~ 9 隨機數字,如果爲 0 則免單。即:十分之一概率免單
val free = Random().nextInt(10)
if (free == 0) {
return 0.0
}
}
return price
}
fun getUnit(): Double {
...
}
fun getNumber(): Int {
...
}
fun todayIsLoversDay(): Boolean {
...
}
private fun isCouple(): Boolean {
...
}
fun todayIsMiddleAutumn(): Boolean {
...
}
fun todayIsNationalDay(): Boolean {
...
}
}
看着那個只屬於七夕節的 gifts 變量
老過像看着自己白襯衫上的油漬一樣難受
以後每次收費時都會生成一個只有七夕節纔會用到的變量
都是因爲老闆的需求太奇葩才讓這個程序看起來亂糟糟的
由於這個類做了修改本來已經測試通過的代碼又得重測一遍
阿對打開了 LoversDayBill 類將其修改如下
class LoversDayBill : Bill() {
val gifts = listOf("flower", "chocolate", "9.9 discount")
override fun discount(price: Double): Double {
if (!isCouple()) return price
if (price > 99) {
val lucky = Random().nextInt(gifts.size)
println("Congratulations on getting ${gifts[lucky]}!")
}
return price * 0.77
}
fun isCouple(): Boolean {
...
}
}
當老闆看完老過和阿對的代碼後
再次興奮地提出新需求時
老過頓時暈了過去…
比賽真是太焦灼了
最後贏得獎勵的是?
第三個參賽者
老闆的傻兒子
他完全不會寫程序
但他使用 Ctrl+C,Ctrl+V
拷貝了阿對的代碼