通過具體業務場景學習工廠模式與策略模式
阿新 • • 發佈:2021-02-06
-
入職新公司後熟悉業務過程中收到一個需求,優化一部分程式碼邏輯,優化時考慮業務的複雜性於是就想到使用設計模式優化這部分邏輯,將原來強耦合的邏輯拆分,便於以後的維護,分析之後確定使用工廠模式與策略模式。
-
先說下具體業務邏輯:首先業務邏輯中物件分為三個維度,分別為單票、大包、批次,每個維度需要執行不同的邏輯,執行邏輯就需要不同的策略來判斷;這裡策略有兩種情況,分別為首次和重算,最後執行的邏輯則是請求其它服務的具體實現。
-
基於這種場景,首先考慮就是對於維度的拆分,單票、大包、批次都有不同的列舉狀態來判斷,這裡我考慮的就是通過工廠模式判斷列舉值建立物件。第二,對於首次和重算的策略,單票和大包觸發策略的邏輯又不相同,這裡我就考慮使用策略模式首先不同維度下的不同策略的生成。
工廠模式實現:
程式碼如下:
建立通用維度的一個物件Dimension,該物件是一個介面呈現的
public interface Dimension {
public void create();
}
建立兩個具體的物件Parcel、Container實現Dimension,重寫方法
public class Parcel implements Dimension {
@Override
public void create() {
//具體邏輯
}
}
public class Container implements Dimension {
@Override
public void create() {
//具體邏輯
}
}
建立工廠及實現類
//建立一個工廠介面,定義一個建立物件的方法
public interface DimensionFactory {
public Dimension create(Class c) throws ClassNotFoundException, IllegalAccessException, InstantiationException;
}
//建立工廠介面的實現類,用於實現具體的維度物件
public class Factory implements DimensionFactory {
@Override
public Dimension create(Class c) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Dimension dimension = (Dimension)Class.forName(c.getName()).newInstance();
return dimension;
}
}
- 工廠模式主要實現為建立不同的維度物件,具體需要建立哪個物件不需要我自己去判斷,在工廠中實現這個判斷邏輯,我最終只負責接收建立的物件即可,這也是我對工廠模式的理解。將建立物件的具體業務邏輯封裝在工廠中,使用時只傳遞物件的狀態即可,最終在工廠中會生產出我們想要的物件。並且這樣很好的封裝了業務邏輯,將物件的建立與業務邏輯拆分,由工廠實現即可。
策略模式實現:
策略模式:可以理解為定義多種策略,每種策略都進行封裝,這是物件的一種行為實現。
策略模式實現如下:
建立策略介面
建立具體策略實現類實現策略介面
//策略介面
public interface Tactics {
void router();
}
//具體策略實現,首次路由策略
public class FirstRouter implements Tactics {
@Override
public void router() {
//首次路由邏輯
}
}
//具體策略實現,二次路由實現
public class SecondRouter implements Tactics {
@Override
public void router() {
//路由重算邏輯
}
}
建立封裝策略類,封裝策略的具體實現
//封裝策略,將策略的具體實現進行封裝,禁止外部直接訪問該具體實現過程
public class RouterPackage {
private Tactics tactics = null;
public RouterPackage(Tactics tactics) {
this.tactics = tactics;
}
public void toDo() {
tactics.router();
}
}
通過業務具體實現過程:
//建立父類介面
public abstract class RouterImpl {
public abstract void router(long dimensionId);
public void doRouter(long dimensionId,int router) {
}
}
//單票首次路由邏輯:
public class ParcelFirstRouter extends RouterImpl{
@Override
public void router(long dimensionId) {
//實現邏輯
}
}
//包裹首次路由實現:
public class ContainerFirstRouter extends RouterImpl{
@Override
public void router(long dimensionId) {
//實現邏輯
}
}
工廠實現:
//建立工廠
public abstract class RouterFactory {
abstract RouterImpl createRouter(Class c);
}
//工廠實現類實現具體的策略
public class FirstRouterFactory extends RouterFactory
{
@Override
RouterImpl createRouter(Class c) {
RouterImpl router = null;
try {
router = (RouterImpl)Class.forName(c.getName()).newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return router;
}
}
將生成的策略執行具體的策略邏輯
public class RouterContext {
private RouterImpl routerImpl;
public RouterContext(RouterImpl router) {
this.routerImpl = router;
}
public void doRouter(long id) {
//具體的執行邏輯
}
}
將工廠模式與策略模式結合實現
public class FactoryAndTactis {
public void sendRouter(long id) {
//建立工廠
ParcelFirstRouterFactory firstRouterFactory = new ParcelFirstRouterFactory();
DimensionEntity parcel = getDimension(id);
//執行首次路由
if (parcel.getType == Dimension.PARCEL_FIRST) {
//首次路由
ParcelFirstRouter parcelFirstRouter = firstRouterFactory.createRouter(ParcelFirstTactis.class);
RouterContext routerContext = new RouterContext(parcelFirstRouter);
routerContext.doRouter(parcel.getId);
} else if (parcel.getType == Dimension.PARCEL_SECOND) {
//二次路由
}
}
}
通過以上實現,工廠模式可以幫助我們生產具體的策略物件,策略模式保證策略物件可以自由的切換而不需要改動其它邏輯,從而達到解耦的目的。如果需要新增一種策略時,直接實現RouterImpl介面即可,無需其它改動。