多個if-else代碼:
@RunWith(SpringRunner.class) @SpringBootTest public class EducationalBackgroundTest { private int year = 6; @Test public void normalIfElse(){ if ( year == 6){ System.out.println("小學畢業"); }else if ( year == 9){ System.out.println("初中畢業"); }else if ( year == 12){ System.out.println("高中畢業"); }else { System.out.println("未知學習時間"); } } }
上面只統計了3個學習時間,如果我們要寫其他的學習時間就需要繼續添加if-else,如果業務很復雜,那么這個代碼看起來會很亂,不方便維護;
下面用策略模式和工廠模式優化該if-else;
1. 定義抽象策略角色(接口)
public interface EducationalBackground { void process(); }
2. 編寫具體策略角色(實現策略角色接口)
小學畢業策略角色:
import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; @Component public class Primary implements EducationalBackground,InitializingBean { @Override public void process() { System.out.println("小學畢業"); } @Override public void afterPropertiesSet() throws Exception { EducationBackgroundFactory.put(6,this); } }
這里的InitializingBean接口(具體看Spring Bean的生命周期)只有一個方法afterPropertiesSet,實現了該接口的bean初始化會調用這個方法;
再寫一個策略角色“初中畢業”:
import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; @Component public class Junior implements EducationalBackground,InitializingBean { @Override public void process() { System.out.println("初中畢業"); } @Override public void afterPropertiesSet() throws Exception { EducationBackgroundFactory.put(9,this); } }
3. 環境角色,內部持有一個策略類的引用
簡單工廠模式
import java.util.HashMap; import java.util.Map; import java.util.Optional; public class EducationBackgroundFactory { private static Map<Integer,EducationalBackground> educationMap = new HashMap<>(); private EducationBackgroundFactory(){} private final static EducationalBackground EMPTY = new EmptyDesc(); /** * 將對應年數的學歷對象注冊到Map中 * @param year * @param educationalBackground */ public static void put(int year,EducationalBackground educationalBackground){ educationMap.put(year,educationalBackground); } /** *獲得對應學歷對象 * @param year */ public static EducationalBackground get(int year){ EducationalBackground educationalBackground = educationMap.get(year); //沒有對應year返回EMPTY return Optional.ofNullable(educationalBackground).orElse(EMPTY); } private static class EmptyDesc implements EducationalBackground{ @Override public void process() { System.out.println("未知的學習時間year"); } } }
測試方法:
@RunWith(SpringRunner.class) @SpringBootTest public class EducationalBackgroundTest { private int year = 6; /** * 設計之后僅需兩行代碼 */ @Test public void design(){ EducationalBackground educationalBackground = EducationBackgroundFactory.get(year); educationalBackground.process(); } }
有關於year的參數最好是配置在配置文件中,比如項目已上線,只需要修改配置文件中的內容即可修改對應的引用,而不需要修改代碼(修改了代碼需要發布)!
參考來源: