代碼重構:用工廠+策略模式優化過多的if else代碼塊
最近在工作中優化了一段冗餘的if else代碼塊,感覺對設計模式的理解和運用很有幫助,所以分享出來。鑑於原代碼會涉及到公司的隱私,因此就不貼出來了。下面以更加通俗易懂的案例來解析。
假如寫一個針對員工上班不遵守制度做相應懲罰的程序,比如,上班遲到:罰100;上班睡覺:罰1000;上班早退:警告;上班玩遊戲:嚴重警告;上班談戀愛:開除等,通常都會這樣寫:
public class WorkPunish { public static void main(String[] agrs){ String state ="late"; punish(state); } public static void punish(String state){ if ("late".equals(state)){ System.out.println("罰100"); }else if ("sleep".equals(state)){ System.out.println("罰1000"); }else if ("early".equals(state)){ System.out.println("警告"); }else if ("play".equals(state)){ System.out.println("嚴重警告"); }else if ("love".equals(state)){ System.out.println("開除"); } } }
可以看到,每增加一種情況都要增加一個if else判斷,這樣會造成這段代碼非常長,可讀性差、不易維護。下面就用靜態工廠+策略模式來重構這段代碼(對於靜態工廠模式和策略模式不知道的同學請自行百度哈
先說說思路:1、定義一個處罰的接口 ,包含一個執行處罰的方法
2、每一種情況的處罰都抽象成一個具體處罰類並繼承處罰接口(策略模式)
3、定義一個靜態工廠類,用來根據情況生產具體處罰對象,然後執行處罰的方法(靜態工廠模式)。
代碼如下:
package com.test.punish;
public interface IPunish {
void exePunish();
}
package com.test.punish; import org.springframework.beans.factory.InitializingBean; public class LatePunish implements IPunish,InitializingBean{ public void exePunish() { System.out.println("罰100"); } public void afterPropertiesSet(){ PunishFactory.registerPunish("late", this); } }
package com.test.punish; import org.springframework.beans.factory.InitializingBean;
public class SleepPunish implements IPunish,InitializingBean{
public void exePunish() {
System.out.println(“罰款1000”);
}
public void afterPropertiesSet(){
PunishFactory.registerPunish(“sleep”, this);
}
}
package com.test.punish; import org.springframework.beans.factory.InitializingBean;
public class EarlyPunish implements IPunish,InitializingBean{
public void exePunish() {
System.out.println(“警告”);
}
public void afterPropertiesSet(){
PunishFactory.registerPunish(“early”, this);
}
}
早退處罰類剩下的處罰類就不貼出來了。
package com.test.punish; import java.util.HashMap; import java.util.Map; public class PunishFactory { private static Map<String,IPunish> punishMap = new HashMap<String,IPunish>();private PunishFactory() {}private static final IPunish EMPTY = new EmptyPunish(); //獲取 public static IPunish getPunish(String state) { IPunish result = punishMap.get(state); return result == null ? EMPTY : result; } //將處罰對象註冊到這裏 public static void registerPunish(String state,IPunish o){ punishMap.put(state, o); } private static class EmptyPunish implements IPunish { public void exePunish() { // Empty class } } }
重構後,處罰邏輯就可以這麼寫了,兩行代碼搞定
public class WorkPunish { public static void main(String[] agrs){ String state ="late"; punish(state); } //重構後的處罰邏輯 public static void punish(String state){
//靜態工廠類獲取處罰對象 IPunish punish = PunishFactory.getPunish(state);
//執行處罰邏輯 punish.exePunish(); } }
重構後的處罰邏輯簡單、清晰,後續新增一種情況,只需定義一個相應的類即可,根本不需要修改處罰邏輯,完全解耦合,這大大提高了代碼的可讀性和可維護性。
不過,運用靜態工廠+策略模式,也存在弊端,那就是會增加很多類;但是,當每種情況的邏輯代碼很多、很複雜的時候,那麼這個弊端就可以忽略不計,其優勢就完全展示出來了。