策略模式+工廠模式+模板模式徹底取代 if...else...


在平時開發中,有時避免不了使用大量判斷,簡單處理的話就使用if...else...了,但過多層的if else對於性能有很大的開銷,而且業務復雜的話,耦合太重,對於后期的拓展也不是很友好,所以使用策略模式。

1. 策略+工廠實現相同業務抽象

策略模式:一種解耦的方法,它對算法進行封裝,使得算法的調用和算法本身分離。使用策略模式客戶端代碼不需要調整,算法之間可以互相替換,因為不同的算法實現的是同一個接口。策略模式是一種對象行為型模式。策略模式符合“開閉原則”。

策略模式包括如下角色:

  • Context :環境類

  • Strategy:抽象策略類

  • ConcreteStrategy:具體策略類

下面簡單抽象下業務邏輯:

String name = "shaqiang";

if(name.equals("saobin")){
    System.out.println("I am SaoBin");
}else if(name.equals("shaqiang")){
    System.out.println("I am ShaQiang");
}else if(name.equals("weifeng")){
    System.out.println("I am WeiFeng");
}

有成員“騷斌”、“傻強”、“偉峰”···,其執行邏輯基本一樣,基於策略模式對其進行改造:

1.1 定義策略接口

將成員的業務方法抽象為統一的策略接口。其中 InitializingBean 接口來自Spring框架,用於實現環境的統一工廠。

import org.springframework.beans.factory.InitializingBean;

/**
 * 策略總接口*/
public interface NameHandler extends InitializingBean {
    /**
     * 輸出名稱
     * @param name
     */
    public void myName(String name);

}

1.2 實現策略工廠

此處的工廠即策略模式下的 “環境類” 要素,功能為根據不同的name找到其對應的不同的策略實現,實現方法為將實現NameHandler接口的類都裝載到strategyMap里,除使用工廠實現外,也可以使用枚舉+代理實現。

import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 工廠設計模式*/
public class NameSetFactory {

    private static Map<String, NameHandler> strategyMap = new HashMap<>();

    /**
     * 根據name獲取對應的handler實現
     * @param name
     * @return
     */
    public static NameHandler getInvokeStrategyMap(String name){
        return strategyMap.get(name);
    }

    /**
     * 注冊
     * @param name
     * @param handler
     */
    public static void register(String name, NameHandler handler){
        if(StringUtils.isEmpty(name)||null == handler){
            return;
        }
        strategyMap.put(name,handler);
    }
}

1.3 為各成員實現各自的具體策略實現類

將各自實現類聲明為組件(用於維護工廠),org.springframework.beans.factory.InitializingBean#afterPropertiesSet內部實現工廠注冊。

import org.springframework.stereotype.Component;

/**
 * saobin策略實現*/
@Component
public class SaoBinHandler implements NameHandler {

    /**
     * 輸出名稱
     * @param name
     */
    @Override
    public void myName(String name) {
        System.out.println("I am SaoBin");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        NameSetFactory.register("saobin",this);
    }
}
import org.springframework.stereotype.Component;

/**
 * shaqiang策略實現*/
@Component
public class ShaQiangHandler implements NameHandler {

    /**
     * 輸出名稱
     * @param name
     */
    @Override
    public void myName(String name) {
        System.out.println("I am ShaQiang");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        NameSetFactory.register("shaqiang",this);
    }
}
import org.springframework.stereotype.Component;

/**
 * weifeng策略實現*/
@Component
public class WeiFengHandler implements NameHandler {

    /**
     * 輸出名稱
     * @param name
     */
    @Override
    public void myName(String name) {
        System.out.println("I am WeiFeng");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        NameSetFactory.register("weifeng",this);
    }
}

1.4 新增if邏輯拓展

 如上,如果后續再加新成員的業務,只需要實現其對應的具體策略類即可,不需要關注其對其他成員的業務是否有影響。

2. 策略模式+工廠模式+模板模式實現不同業務

現在來了新需求,之前成員實現的方法基本一致,但現在要求:“騷斌”實現打印名稱,“傻強”實現跳舞,“偉峰”實現打印名稱和跳舞,后續隨時會有新增成員和新增功能,基於上面的實現,可以在策略總接口中新增跳舞方法,實現如下:

 

 可以看出,在總策略接口中新增“跳舞”方法后,沒有該功能的“騷斌”也需要實現它,這個就很不友好了。下面對其進行改造:

2.1 模板設計模式改造總策略接口

將原先的接口改造為抽象類,實現模板模式,所有的功能在類中定義,子類要實現具體功能,重寫即可。

import org.springframework.beans.factory.InitializingBean;

/**
 * 策略抽象類(模板)
 */
public abstract class AbstractNameHandler implements InitializingBean {
    /**
     * 輸出名稱
     * @param name
     */
     public void myName(String name){
         throw new UnsupportedOperationException();
     };

    /**
     * 跳舞
     * @param name
     */
    public void dance(String name){
        throw new UnsupportedOperationException();
    };

}

2.2 策略實現

各成員只需實現其對應的策略方法即可。

如下,測試成員功能,對於有具體實現的方法,成員會執行,如果沒有具體實現,會拋出異常。

 經過上面改造,后面如果新增成員或者新功能實現,新增策略實現即可。這種改造符合開閉原則,適用較為復雜的邏輯判斷。


免責聲明!

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



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