(策略模式+工廠模式+map)套餐 Kill 專案中的switch case
接手新任務:接入第三家存證機構,看之前的程式碼使用了swith case判斷使用哪家存證機構,每家存證機構的實現邏輯不一樣 程式碼的壞味道:多層swich case。多層swich case不好維護,是時候應該重構了,
優化前的程式碼
為了便於理解,舉個沒有業務邏輯的例子,基於這個例子上進行優化。 現在是12:47,舉個飯後吃水果的例子哈哈哈(逃 假設我們可以選擇的水果有香蕉、西瓜和蘋果。吃香蕉的話我們得先剝皮,吃西瓜的話得先用水果刀切一下,如果是蘋果的話就直接吃了。將這個場景轉化為程式碼:
public class EatFruit { private static final String APPLE = "apple"; private static final String BANANA = "banana"; private static final String WATERMELON = "watermelon"; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); //選擇的水果種類 String fruitType = scanner.nextLine(); switch (fruitType) { case APPLE: eatApple(); break; case BANANA: eatBanana(); break; case WATERMELON: eatWatermelon(); break; } } private static void eatBanana() { System.out.println("吃香蕉了,需要先剝下皮"); } private static void eatApple() { System.out.println("是蘋果,可以直接吃"); } private static void eatWatermelon() { System.out.println("吃西瓜了,但是還得弄把水果刀切一下先"); } } 複製程式碼
這個例子程式碼量不是很大,但是實際專案中的場景肯定沒有這麼簡單,多重swich case不好維護,並且萬一又加了一樣水果,還得繼續加一層case...

很容易想到策略模式(簡單的理解就是多型),水果都有吃的一個動作,但是每種水果的吃法不一樣
使用策略模式進行優化
Fruit.java
public interface Fruit { void eat(); } 複製程式碼
Apple.java
public class Apple implements Fruit { @Override public void eat() { System.out.println("是蘋果,可以直接吃"); } } 複製程式碼
Banana.java
public class Banana implements Fruit { @Override public void eat() { System.out.println("吃香蕉了,需要先剝下皮"); } } 複製程式碼
Watermelon.java
public class Watermelon implements Fruit { @Override public void eat() { System.out.println("吃西瓜了,但是還得弄把水果刀切一下先"); } } 複製程式碼
但是發現即使用了策略模式也難逃型別判斷 EatFruit.java
public class EatFruit { private static final String APPLE = "apple"; private static final String BANANA = "banana"; private static final String WATERMELON = "watermelon"; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); //選擇的水果種類 String fruitType = scanner.nextLine(); Fruit fruit = null; switch (fruitType) { case APPLE: fruit = new Apple(); break; case BANANA: fruit = new Banana(); break; case WATERMELON: fruit = new Watermelon(); break; } fruit.eat(); } } 複製程式碼
使用策略模式具有良好的擴充套件性,兵來將擋,再給我新增十種水果都不怕,水果種類太多會使水果的實現類暴增。現在來一種水果無需在原先的業務類(EatFruit)裡修改很多的程式碼邏輯,只要實現介面並加個條件判斷就好了。但是使用策略模式時,我們需要知道具體的實現類,具體的實現類需要對外暴露
使用工廠模式
將型別判斷放到工廠類中 工廠模式:在建立物件時不會對客戶端暴露建立邏輯,並且是通過使用一個共同的介面來指向新建立的物件,這裡共同的介面就是Fruit。粗暴的講,工廠模式就是把建立同一型別物件邏輯寫在了一個方法裡 FruitFactory .java
public class FruitFactory { public static Fruit getFruit(String fruitType) { if ("apple".equals(fruitType)) { return new Apple(); } if ("banana".equals(fruitType)) { return new Banana(); } return new Watermelon(); } } 複製程式碼
EatFruit .java
public class EatFruit { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); //選擇的水果種類 String fruitType = scanner.nextLine(); Fruit fruit = FruitFactory.getFruit(fruitType); fruit.eat(); } } 複製程式碼
到現在為止EatFruit中的業務程式碼已經很清晰了。 使用工廠模式具有良好的封裝性,這下媽媽再也不用關係建立類的過程,甚至連建立的實際類的都無需關心,實現瞭解耦,實際類的修改變化都不會影響上層業務
但是工廠類中還是有很多if的,革命尚未成功,仍需要進行優化。
map奧特曼來了
FruitFactory.java
public class FruitFactory { private static Map<String, Fruit> fruitMap = new HashMap<>(); static { fruitMap.put("apple", new Apple()); fruitMap.put("banana", new Banana()); fruitMap.put("watermelon", new Watermelon()); } public static Fruit getFruit(String fruitType) { return fruitMap.get(fruitType); } } 複製程式碼
通過使用map, fruitType
與 <T extend Fruit>
進行一一對映,和條件判斷說byebye~,程式碼也很優雅 最終專案結構類圖:
