考慮這樣乙個實際應用:就是如何實現靈活的獎金計算。
獎金計算是相對複雜的功能,尤其是對於業務部門的獎金計算方式,是非常複雜的,除了業務功能複雜外,另外乙個麻煩之處是計算方式還經常需要變動,因為業務部門經常通過調整獎金的計算方式來激勵士氣。
先從業務上看看現有的獎金計算方式的複雜性:
看了上面獎金計算的問題,所幸我們只是來學習設計模式,並不是真的要去實現整個獎金計算體系的業務,因此也沒有必要把所有的計算業務都羅列在這裡,為了後面演示的需要,簡化一下,演示用的獎金計算體系如下:
乙個人的獎金分成很多個部分,要實現獎金計算,主要就是要按照各個獎金計算的規則,把這個人可以獲取的每部分獎金計算出來,然後計算乙個總和,這就是這個人可以得到的獎金。
(1)為了演示,先準備點測試資料,在記憶體中模擬資料庫,示例**如下:
/**
* 在記憶體中模擬資料庫,準備點測試資料,好計算獎金
*/public class tempdb
/*** 記錄每個人的月度銷售額,只用了人員,月份沒有用
*/public static mapmapmonthsalemoney =
new hashmap();
static
}
(2)按照獎金計算的規則,實現獎金計算,示例**如下:
/**
* 計算獎金的物件
*/public class prize
return prize;
} /**
* 計算某人的當月業務獎金,引數重複,就不再注釋了
*/private double monthprize(string user, date begin, date end)
/*** 計算某人的累計獎金,引數重複,就不再注釋了
*/public double sumprize(string user, date begin, date end)
/*** 判斷人員是普通人員還是業務經理
* @param user 被判斷的人員
* @return true表示是業務經理,false表示是普通人員
*/private boolean ismanager(string user)
return false;
} /**
* 計算當月團隊業務獎,引數重複,就不再注釋了
*/public double groupprize(string user, date begin, date end)
double prize = group * 0.01;
system.out.println(user+"當月團隊業務獎金"+prize);
return prize;
}}
(3)寫個客戶端來測試一下,看看是否能正確地計算獎金,示例**如下:
public class client
}
測試執行的結果如下:
張三當月業務獎金300.0
張三累計獎金1000.0
**********張三應得獎金:1300.0
李四當月業務獎金600.0
李四累計獎金1000.0
**********李四應得獎金:1600.0
王五當月業務獎金900.0
王五累計獎金1000.0
王五當月團隊業務獎金600.0
**********王經理應得獎金:2500.0
看了上面的實現,挺簡單的嘛,就是計算方式麻煩點,每個規則都要實現。真的很簡單嗎?仔細想想,有沒有什麼問題?
對於獎金計算,光是計算方式複雜,也就罷了,不過是實現起來會困難點,相對而言還是比較好解決的,不過是用程式把已有的演算法表達出來。
最痛苦的是,這些獎金的計算方式,經常發生變動,幾乎是每個季度都會有小調整,每年都有大調整,這就要求軟體的實現要足夠靈活,要能夠很快進行相應調整和修改,否則就不能滿足實際業務的需要。
舉個簡單的例子來說,現在根據業務需要,需要增加乙個「環比增長獎金」,就是本月的銷售額比上個月有增加,而且要達到一定的比例,當然增長比例越高,獎金比例越大。那麼軟體就必須要重新實現這麼個功能,並正確的新增到系統中去。過了兩個月,業務獎勵的策略發生了變化,不再需要這個獎金了,或者是另外換了乙個新的獎金方式了,那麼軟體就需要把這個功能從軟體中去掉,然後再實現新的功能。
那麼上面的要求該如何實現呢?
很明顯,一種方案是通過繼承來擴充套件功能;另外一種方案就是到計算獎金的物件裡面,新增或者刪除新的功能,並在計算獎金的時候,呼叫新的功能或是不呼叫某些去掉的功能,這種方案會嚴重違反開-閉原則。
還有乙個問題,就是在執行期間,不同人員參與的獎金計算方式也是不同的,舉例來說:如果是業務經理,除了參與個人計算部分外,還要參加團隊獎金的計算,這就意味著需要在執行期間動態來組合需要計算的部分,也就是會有一堆的if-else。
總結一下,獎金計算面臨如下問題:
上面描述的獎金計算的問題,絕對沒有任何誇大成分,相反已經簡化不少了,還有更多麻煩沒有寫上來,畢竟我們的重點在設計模式,而不是業務。
把上面的問題抽象一下,設若有乙個計算獎金的物件,現在需要能夠靈活的給它增加和減少功能,還需要能夠動態的組合功能,每個功能就相當於在計算獎金的某個部分。
現在的問題就是:如何才能夠透明的給乙個物件增加功能,並實現功能的動態組合呢?
也可以直接在卓越網上搜尋《研磨設計模式》
未完待續
研磨設計模式之橋接模式 1
來寫乙個大家既陌生又熟悉的設計模式,也是非常實用的乙個設計模式,那就是橋接模式。說陌生是很多朋友並不熟悉這個設計模式,說熟悉是很多人經常見到或者是下意識的用到這個設計模式,只是不知道罷了。橋接模式是非常實用的乙個模式,下面就來寫寫它。考慮這樣乙個實際的業務功能 傳送提示訊息。基本上所有帶業務流程處理...
研磨設計模式之命令模式 3
可撤銷操作的意思就是 放棄該操作,回到未執行該操作前的狀態。這個功能是乙個非常重要的功能,幾乎所有gui應用裡面都有撤消操作的功能。gui的選單是命令模式最典型的應用之一,所以你總是能在選單上找到撤銷這樣的選單項。既然這麼常用,那該如何實現呢?有兩種基本的思路來實現可撤銷的操作,一種是補償式,又稱反...
設計模式之裝飾設計模式
1.目的 動態擴充套件類的行為 開閉原則 對擴充套件開放,對修改關閉 2.要點 裝飾類和被裝飾類都實現同乙個介面或者繼承同乙個類 3.具體實現 被裝飾元件介面 被裝飾元件實現類實現 抽象類構建被裝飾元件實現被裝飾元件介面 裝飾類繼承抽象類 裝飾類 重寫抽象類方法 裝飾 4.例項 被裝飾類介面 pub...