策略模式消除惡心的if else


一 . 什么是策略模式

   策略模式是對算法的包裝,把使用算法的責任和算法本身分隔開,委派給不同的對象管理。策略模式通常把一系列的算法包裝到一系列的策略類里面,作為一個抽象策略類的子類。

   簡單來說就是就定義一個策略接口,子類策略去實現該接口去定義不同的策略。然后定義一個環境(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; }

 

 

未完待續=======

 

 

 

部分參考 : https://www.cnblogs.com/zdd-java/p/6143935.html 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM