策略模式簡單來說就是將業務和實現業務的具體方法剝離開來
依然以倉庫揀貨來說,合併揀貨分單揀貨是一種模式,但具體根據所出庫單中的品是什麼類型,從哪種類型倉庫出,還是要有具體的揀貨策略來生成揀貨列表
比如 服裝倉按動線進行揀貨,快消倉分整揀散揀,數碼倉的品要掃碼標記SN與單據關係出庫
那麼就要根據各種不同的倉庫劃分出不同的揀貨列表創建方式,這樣就把揀貨這個業務本身,和具體揀貨列表的生成進行剝離。不寫死在具體業務中
首先建立策略模式的頂層接口
package strategy;
import java.util.List;
import bean.PickDoc;
import bean.PickList;
/**
- 揀貨策略頂層接口
- @author [email protected]
-
*/
public interface IPickStrategy {public List<PickList> pickStrategy(List<PickDoc> list) ;
}
然後依次建立服裝,數碼,快消3種倉庫的具體揀貨列表策略
package strategy;
import java.util.List;
import bean.PickDoc;
import bean.PickList;
/**
- 服裝倉揀貨策略
- @author [email protected]
-
*/
public class ClothPickStrategy implements IPickStrategy {@Override
public List<PickList> pickStrategy(List<PickDoc> list) {// TODO Auto-generated method stub System.out.println("根據單據展開服裝倉揀貨策略"); return null;
}
}
package strategy;
import java.util.List;
import bean.PickDoc;
import bean.PickList;
/**
- 數碼倉揀貨策略
- @author [email protected]
-
*/
public class DigitalPickStrategy implements IPickStrategy{@Override
public List<PickList> pickStrategy(List<PickDoc> list) {// TODO Auto-generated method stub System.out.println("根據單據展開數碼倉揀貨策略"); return null;
}
}
package strategy;
import java.util.List;
import bean.PickDoc;
import bean.PickList;
/**
- 快消倉揀貨策略
- @author [email protected]
-
*/
public class FmcgPickStrategy implements IPickStrategy{@Override
public List<PickList> pickStrategy(List<PickDoc> pickDoc) {// TODO Auto-generated method stub System.out.println("根據單據展開快消倉揀貨策略"); return null;
}
}
然後對以前定義的揀貨接口進行修改,引入設置揀貨策略的方法,依次修改合併揀貨與分單揀貨的實現
package builder;
import java.util.List;
import bean.PickDoc;
import bean.PickList;
import bean.PickTask;
import strategy.IPickStrategy;
/**
- 定義要完成的動作
- @author mas
-
*/
public interface IPickTask {//計算要揀貨的SKU列表
public List<PickList> getPickList(List<PickDoc> list);//計算拆分的揀貨任務
public List<PickTask> getPickTask(List<PickList> list);//設置揀貨策略
public void setPickStrategy(IPickStrategy pickStrategy);
}
然後進行示例調用
package strategy;
import java.util.ArrayList;
import java.util.List;
import bean.PickDoc;
import builder.IPickTask;
import builder.UnionPickTask;
public class PickStrategyMain {
public static void main(String[] args) {
//揀貨單據列表
List<PickDoc> list = new ArrayList<PickDoc>();
//假設當前是電子倉,要用電子倉的揀貨策略
IPickStrategy pickStrategy = new DigitalPickStrategy();
//揀貨模式爲合併揀貨
IPickTask pickTask = new UnionPickTask();
//設置揀貨策略
pickTask.setPickStrategy(pickStrategy);
//獲取揀貨列表
pickTask.getPickList(list);
}
}
調用效果
這裏會看到有個做靜態代理演示代碼的StaticPickTaskProxy.java報錯。
這是因爲這個靜態代理類是要實現IPickTask這個頂層接口的所有方法,
這裏就發現靜態代理的缺點了。
另外也可以看到面向接口開發的優勢,可以快速觀察到所涉及業務子類的影響。如果不面向接口編程,那麼可能會在大的業務調整時導致某些也涉及到業務的類被我們忽略修改,同時因爲業務測試的分支難以覆蓋而造成潛在隱患