一 . 什么是策略模式
策略模式是對算法的包裝,把使用算法的責任和算法本身分隔開,委派給不同的對象管理。策略模式通常把一系列的算法包裝到一系列的策略類里面,作為一個抽象策略類的子類。
簡單來說就是就定義一個策略接口,子類策略去實現該接口去定義不同的策略。然后定義一個環境(Context)類,以策略接口作為成員變量,根據環境來使用具體的策略。
二. 使用場景
業務中有要根據不同條件來使用不同算法的情況下,並且這些算法可以抽象的,就可以去使用。例如說,根據用戶的分類,可以分為普通用戶、白金用戶、鑽石用戶等,不同種類的用戶結算時需要不同的結算算法。如果不使用的話,那么可能造成每增加用戶種類就需要去,就要在業務代碼上去增加一個判斷,造成的后果就是代碼越來越冗余,不利於維護,也不方便閱讀。
三. 如何使用
1.定義策略接口
1 public interface Strategy { 2 3 public Double count(Double pay); 4 }
2.不同策略實現該策略接口
//普通會員 全款 public class StrategyNormal implements Strategy { @Override public Double count(Double pay) { return pay ; } } //白金會員98折 public class StrstegyPlatinum implements Strategy { @Override public Double count(Double pay) { return pay * 0.98; } } //鑽石會員9折 public class StrstegyDiamond implements Strategy { @Override public Double count(Double pay) { return pay * 0.9; } }
3.定義策略環境
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public Double count(Double pay){ return strategy.count(pay); }
4.定義策略工廠
為什么有策略工廠?因為在策略環境Context 中需要具體的策略實現類去進行算法計算的,所以需要根據客戶端給出的條件去具體的拿到策略類。
首先我們定義一個枚舉類,定義不同的用戶級別
public enum CustomerType { NORMAL(0,"普通用戶"), PLATINUM(1,"白金用戶"), DUAMOND(2,"鑽石用戶"); private int index; private String message; CustomerType(int index, String message) { this.index = index; this.message = message; } @Override public String toString() { return "CustomerType{" + "index=" + this.index + ", message='" + this.message + '\'' + '}'; }
定義具體的策略工廠。
public class StrategyFactory { private static Map<CustomerType, Strategy> strstegyMap = new HashMap<CustomerType,Strategy>(); public static void register(CustomerType type, Strategy strategy){ strstegyMap.put(type,strategy); } private StrategyFactory() { } public static Strategy getInstance(CustomerType type){ return strstegyMap.get(type); } }
5.調用
public static void main(String[] args) { Double pay = 100.00D; Strategy strategyNormal = StrategyFactory.getInstance(CustomerType.NORMAL); Context contextNormal = new Context(strategyNormal); System.out.println(CustomerType.NORMAL.toString() + "應付:" + contextNormal.count(pay)); Strategy strategyPlatinum = StrategyFactory.getInstance(CustomerType.PLATINUM); Context contextPlatinum = new Context(strategyPlatinum); System.out.println(CustomerType.PLATINUM.toString() + "應付:" +contextPlatinum.count(pay)); Strategy strategyDuamond = StrategyFactory.getInstance(CustomerType.DUAMOND); Context contextDuamond = new Context(strategyDuamond); System.out.println(CustomerType.DUAMOND.toString() + "應付:"+contextDuamond.count(pay)); }
結果:
CustomerType{index=0, message='普通用戶'}應付:100.0 CustomerType{index=1, message='白金用戶'}應付:98.0 CustomerType{index=2, message='鑽石用戶'}應付:90.0
這樣的話,以后如果還要加別的會員類型,直接在枚舉兌現各種增加類型,然后實現策略接口,在策略工廠中稍作修改就可以實現功能,不用去修改業務主體代碼,減少了if else 的判斷。
四、優化
每增加一個用戶類型后,還是需要去修改策略工廠類,我在想有沒有辦法去根據客戶端的類型,動態加載子類策略的方法。
后來看到有網友通過使用反射以及注解的方式實現了動態加載,根據這個思路繼續做一個調整。
//客戶端類型注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface CustomerTypeAnnotation { CustomerType customerType() default CustomerType.NORMAL; }
未完待續=======