生活随笔
收集整理的這篇文章主要介紹了
09、策略模式
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
策略模式與工廠模式最大的區(qū)別在于,策略模式注重的是對算法的維護,也可以理解為對算法的封裝。而工廠模式,則只是負(fù)責(zé)創(chuàng)建類,在剛接觸策略模式時候,往往與工廠模式容易產(chǎn)生混淆。 官方對策略模式的解釋: 它定義了算法家族,分別封裝起來,讓他們之間可以互換,此模式,讓算法的變化不會影響到使用算法的客戶。
從此模式開始,每次總結(jié)的時候畫出一個UML圖。
此例子結(jié)合商場搞活動銷售活動,商品價格打折、以及返價活動。 任何一種活動,最終都要有一個計算結(jié)果的方法,所以對此方法進行抽象:
public interface PriceCalculate { public abstract double getFinalPrice();} 然后對其進行實現(xiàn),分別為不搞活動,折扣,返現(xiàn)活動,分別如下:
public class NormalPrice implements PriceCalculate { private double finalPrice = 0d; public double getFinalPrice() { // TODO Auto-generated method stub return finalPrice; } public NormalPrice(double sourcePrice){ this.finalPrice = sourcePrice; }} 然后是折扣活動:
public class DebetPrice implements PriceCalculate { private double finalPrice = 0d; @Override public double getFinalPrice() { return finalPrice; } public DebetPrice(double sourcePrice,double debet){ this.finalPrice = Calculate.mul(sourcePrice, debet); }} Calculate為工具類,具體代碼在最后。 然后是折現(xiàn)活動:
public class ReturnPrice implements PriceCalculate { private double finalPrice = 0d; @Override public double getFinalPrice() { // TODO Auto-generated method stub return finalPrice; } /**滿多少價反錢活動 * @param sourcePrice 原價 * @param conditionPrice 返現(xiàn)金消費額度 * @param returnPrice 返現(xiàn)金力度 */ public ReturnPrice(double sourcePrice,double conditionPrice,double returnPrice){ this.finalPrice = sourcePrice; if( sourcePrice >= conditionPrice ){ double times = Math.floor(Calculate.div(sourcePrice, conditionPrice)) ; int count = times>=1? (int)times:0; while(count-->0){ this.finalPrice = Calculate.sub(sourcePrice,returnPrice); } } }} 其中的Calculate為工具類,具體如下:
package com.yp.learn.util;import java.math.BigDecimal;public class Calculate { // 默認(rèn)除法運算精度 private static final int DEF_DIV_SCALE = 10; private Calculate(){}; /**精確 加法運算 * @param d1 被加數(shù) * @param d2 加數(shù) * @return 和 */ public static double add(double d1,double d2){ BigDecimal b1= new BigDecimal(Double.toString(d1)); BigDecimal b2= new BigDecimal(Double.toString(d2)); return b1.add(b2).doubleValue(); } /** * 提供精確的減法運算。 * @param v1 被減數(shù) * @param v2 減數(shù) * @return 兩個參數(shù)的差 */ public static double sub(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /** * 提供精確的乘法運算。 * @param v1 被乘數(shù) * @param v2 乘數(shù) * @return 兩個參數(shù)的積 */ public static double mul(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供(相對)精確的除法運算,當(dāng)發(fā)生除不盡的情況時,精確到 小數(shù)點以后10位,以后的數(shù)字四舍五入。 * @param v1 被除數(shù) * @param v2 除數(shù) * @return 兩個參數(shù)的商 */ public static double div(double v1, double v2) { return div(v1, v2, DEF_DIV_SCALE); } /** * 提供(相對)精確的除法運算。當(dāng)發(fā)生除不盡的情況時,由scale參數(shù)指 定精度,以后的數(shù)字四舍五入。 * @param v1 被除數(shù) * @param v2 除數(shù) * @param scale 表示表示需要精確到小數(shù)點以后幾位。 * @return 兩個參數(shù)的商 */ public static double div(double v1, double v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); }} 然后策略模式的核心出來了,幾種類都已經(jīng)實現(xiàn)類,并且都有算法,策略模式要做的,就是 對這個抽象出來的 算法進行 維護,如下:
public class PriceCalculateContext { PriceCalculate cal = null; /**無活動情況 * @param sourcePrice */ public PriceCalculateContext(double sourcePrice){ cal = new NormalPrice(sourcePrice); } /**打折活動 * @param sourcePrice 原價 * @param debet 打折力度 */ public PriceCalculateContext(double sourcePrice,double debet){ cal = new DebetPrice(sourcePrice,debet); } /**返現(xiàn)活動 * @param sourcePrice 原價 * @param conditionPrice 返現(xiàn)所需滿足額度 * @param returnPrice 返現(xiàn)力度 */ public PriceCalculateContext(double sourcePrice,double conditionPrice,double returnPrice){ cal = new ReturnPrice(sourcePrice,conditionPrice,returnPrice); } public double getResult() { return cal.getFinalPrice(); }} 與之前的工廠模式相比較,策略模式并沒有提供創(chuàng)建運算類的工廠類,而只是將這些運算類維護在了PriceCalculateContext類中,并且此類中提供了方法getResult(),此方法所調(diào)用的剛好是算法接口。那么現(xiàn)在,客戶端的代碼就非常的清晰了:
public class Start { public static void main(String[] args) { PriceCalculateContext p = new PriceCalculateContext(100d); System.out.println(p.getResult()); p = new PriceCalculateContext(122.2d, 100d, 15d); System.out.println(p.getResult()); }} 通過構(gòu)造價格計算維護類來計算所得的最終結(jié)果,計算的具體形式完全對客戶端屏蔽。策略模式最明顯的就是對每種策略所實現(xiàn)的算法進行了封裝,在本例中,就是 PriceCalculateContext的getResult的方法,在后續(xù),可以說如果需要新增新的算法,那么我只需要新增新的算法類,然后在PriceCalculateContext增加相應(yīng)的映射即可。在客戶端只需要依據(jù)不同的參數(shù)進行初始化,然后調(diào)用的方法不用發(fā)生任何改變。 UML圖如下:
從類圖上也可以看到,客戶端的代碼只關(guān)聯(lián)PriceCalculateContext類,解耦很成功。
還是強調(diào)一點,策略模式注重對策略的封裝。
總結(jié)分析: 1、比較工廠模式,此模式通過增加算法維護類(PriceCalculateContext),對所有的算法進行封裝,并且在客戶端代碼中,只有此類創(chuàng)建和使用。 2、當(dāng)新增類的時候,需要算法維護類中修改代碼,相當(dāng)于需求和實現(xiàn)做映射關(guān)系。即客戶端代碼依然沒有轉(zhuǎn)移條件判斷。
來自為知筆記(Wiz)
轉(zhuǎn)載于:https://my.oschina.net/u/1182369/blog/406571
總結(jié)
以上是生活随笔為你收集整理的09、策略模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。