一洪囤、背景
很多做業(yè)務(wù)開發(fā)的同學(xué)徒坡,很多認(rèn)為平時寫業(yè)務(wù)代碼
工作就是簡單的增刪改查
,沒有挑戰(zhàn)瘤缩,寫的代碼不會像一些開源框架那么優(yōu)雅
喇完,隨著你積累的經(jīng)驗
越來越多,你應(yīng)該跳出這種思維剥啤,業(yè)務(wù)代碼也可以寫的很優(yōu)雅锦溪,也可以有較好的可讀性
和擴(kuò)展性
。
我們可以觀察公司內(nèi)府怯,或者團(tuán)隊內(nèi)工作時間長一點(diǎn)的同事
寫的代碼刻诊,一般都可以找到可以學(xué)習(xí)的代碼
。如果你讀過Spring源碼
的同學(xué)可以知道牺丙,Spring
代碼有一個非常大的特點(diǎn)就是擴(kuò)展性極強(qiáng)
则涯,他擴(kuò)展性強(qiáng)一個很重要的原因是恰當(dāng)?shù)氖褂昧撕芏嘣O(shè)計模式。
本文將結(jié)合案例分析平時業(yè)務(wù)開發(fā)中使用頻率最高
的兩種設(shè)計模式<<策略模式
>>與<<責(zé)任鏈模式
>>冲簿。
二粟判、策略模式
以支付功能為例子,我們知道支付一般都支持多種支付方式峦剔,我們支付功能在后端發(fā)起档礁,不同的支付方式其實就是策略,我們可以通過策略模式來完成支付功能吝沫。將不同的支付方式代碼進(jìn)行解耦呻澜。
public interface PaymentStrategy {
void pay(double amount);
}
public class WeChatPaymentStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
// 微信支付邏輯
}
}
public class AlipayPaymentStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
// 支付寶支付邏輯
}
}
import java.util.HashMap;
import java.util.Map;
public class PaymentStrategyFactory {
private Map<String, PaymentStrategy> strategies = new HashMap<>();
public void registerStrategy(String name, PaymentStrategy strategy) {
strategies.put(name, strategy);
}
public PaymentStrategy getStrategy(String name) {
return strategies.get(name);
}
}
使用策略模式:
public class Main {
public static void main(String[] args) {
PaymentStrategyFactory factory = new PaymentStrategyFactory();
// 注冊支付策略
factory.registerStrategy("wechat", new WeChatPaymentStrategy());
factory.registerStrategy("alipay", new AlipayPaymentStrategy());
// 獲取支付策略
PaymentStrategy wechatStrategy = factory.getStrategy("wechat");
PaymentStrategy alipayStrategy = factory.getStrategy("alipay");
// 使用支付策略
wechatStrategy.pay(100.0);
alipayStrategy.pay(150.0);
}
}
通過上方實際例子,我們可以發(fā)現(xiàn)策略模式
很好的將不同的支付方式進(jìn)行了解耦
野舶,如果業(yè)務(wù)需要新增一種支付方式,我們不需要改原先的支付方式代碼宰衙,這樣可以達(dá)到對擴(kuò)展開發(fā)平道,對修復(fù)關(guān)閉
的設(shè)計原則,對于測試范圍
也可控了供炼。
三一屋、異步形式的責(zé)任鏈模式
責(zé)任鏈模式在業(yè)務(wù)開發(fā)中也是可以使用頻率高的設(shè)計模式,我們以展示商品為例:
[圖片上傳失敗...(image-3cc4a9-1715505779722)]
商品頁面袋哼,包含商品標(biāo)題冀墨,主圖等基礎(chǔ)信息,商品價格涛贯,商品優(yōu)惠活動诽嘉,商品庫存等等。
在微服務(wù)架構(gòu)中,商品基礎(chǔ)信息虫腋,商品價格骄酗,商品優(yōu)惠活動,商品庫存都是一個獨(dú)立的領(lǐng)域服務(wù)
悦冀,他們通過rpc
進(jìn)行通信趋翻,如果我們一個一個調(diào)用,這樣代碼看起來就是一本流水賬盒蟆,過程式編碼踏烙,整體的響應(yīng)時間也會拉長。最初的想法可能是這樣寫的:
1历等、查詢商品基礎(chǔ)信息
2讨惩、查詢商品價格
3、查詢商品活動
4募闲、查詢商品庫存
由于這幾個服務(wù)邏輯比較獨(dú)立步脓,其實是可以并行調(diào)用,我們可以結(jié)合責(zé)任鏈模式
和CompletableFuture
進(jìn)行優(yōu)化浩螺。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
// 商品信息類
class ProductInfo {
//模擬商品基礎(chǔ)信息
private String basicInfo;
//商品價格
private double price;
//模擬商品活動信息
private String activity;
//模擬商品庫存
private int inventory;
// 省略構(gòu)造函數(shù)靴患、getter和setter
}
// 定義責(zé)任鏈節(jié)點(diǎn)接口 補(bǔ)全商品處理接口
interface ServiceHandler {
CompletableFuture<Void> handle(ProductInfo productInfo);
}
// 實現(xiàn)商品基礎(chǔ)信息補(bǔ)全節(jié)點(diǎn)
class BasicInfoServiceHandler implements ServiceHandler {
@Override
public CompletableFuture<Void> handle(ProductInfo productInfo) {
CompletableFuture<Void> future = new CompletableFuture<>();
// 模擬異步調(diào)用外部服務(wù),修改商品信息對象
CompletableFuture.runAsync(() -> {
// 補(bǔ)充商品基礎(chǔ)信息數(shù)據(jù)
productInfo.setBasicInfo("...");
future.complete(null);
});
return future;
}
}
// 實現(xiàn)商品價格補(bǔ)全節(jié)點(diǎn)
class PriceServiceHandler implements ServiceHandler {
@Override
public CompletableFuture<Void> handle(ProductInfo productInfo) {
CompletableFuture<Void> future = new CompletableFuture<>();
// 模擬異步調(diào)用外部服務(wù)要出,修改商品信息對象
CompletableFuture.runAsync(() -> {
// 補(bǔ)充商品價格數(shù)據(jù)
productInfo.setPrice(100.0);
future.complete(null);
});
return future;
}
}
// 實現(xiàn)商品活動補(bǔ)全節(jié)點(diǎn)
class ActivityServiceHandler implements ServiceHandler {
@Override
public CompletableFuture<Void> handle(ProductInfo productInfo) {
CompletableFuture<Void> future = new CompletableFuture<>();
// 模擬異步調(diào)用外部服務(wù)鸳君,修改商品信息對象
CompletableFuture.runAsync(() -> {
// 補(bǔ)充商品活動數(shù)據(jù)
productInfo.setActivity("...");
future.complete(null);
});
return future;
}
}
// 實現(xiàn)商品庫存服務(wù)節(jié)點(diǎn)
class InventoryServiceHandler implements ServiceHandler {
@Override
public CompletableFuture<Void> handle(ProductInfo productInfo) {
CompletableFuture<Void> future = new CompletableFuture<>();
// 模擬異步調(diào)用外部服務(wù),修改商品信息對象
CompletableFuture.runAsync(() -> {
// 補(bǔ)充商品庫存數(shù)據(jù)
productInfo.setInventory(100);
future.complete(null);
});
return future;
}
}
// 責(zé)任鏈
class ServiceHandlerChain {
private List<ServiceHandler> handlers = new ArrayList<>();
public void addHandler(ServiceHandler handler) {
handlers.add(handler);
}
public ProductInfo execute(ProductInfo productInfo) {
CompletableFuture<Void>[] futures = handlers.stream()
.map(handler -> handler.handle(productInfo))
.toArray(CompletableFuture[]::new);
//等待所有的異步補(bǔ)全任務(wù)處理完成
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(futures);
allOfFuture.join(); // 等待所有異步操作完成
return productInfo;
}
}
調(diào)用責(zé)任鏈患蹂,實現(xiàn)商品信息補(bǔ)全:
public class Main {
public static void main(String[] args) {
// 創(chuàng)建商品信息對象
ProductInfo productInfo = new ProductInfo();
// 創(chuàng)建責(zé)任鏈
ServiceHandlerChain chain = new ServiceHandlerChain();
chain.addHandler(new BasicInfoServiceHandler());
chain.addHandler(new PriceServiceHandler());
chain.addHandler(new ActivityServiceHandler());
chain.addHandler(new InventoryServiceHandler());
// 執(zhí)行責(zé)任鏈
ProductInfo result = chain.execute(productInfo);
// 處理最終的商品信息對象
}
}
通過責(zé)任鏈模式
+CompletableFuture
優(yōu)化調(diào)整或颊,我們將商品各自補(bǔ)全邏輯進(jìn)行拆分
,互不依賴
传于,如果需要展示商品其他信息可以擴(kuò)展新節(jié)點(diǎn)
囱挑,而且每個節(jié)點(diǎn)都是異步化處理
,提升整體響應(yīng)速度
沼溜。
四平挑、總結(jié)
本文結(jié)合實際例子對于業(yè)務(wù)開發(fā)工作中最常用兩個設(shè)計模式進(jìn)行了總結(jié),適當(dāng)使用設(shè)計模式
可以把一些業(yè)務(wù)需求實現(xiàn)的更加優(yōu)雅
系草,對于未來的擴(kuò)展性
也打下了基礎(chǔ)通熄,給后期開發(fā)測試都減少了工作量
,設(shè)計模式可以結(jié)合我們實際業(yè)務(wù)適當(dāng)調(diào)整找都,變成適合我們自己業(yè)務(wù)的模式唇辨,比如上面的異步形式的責(zé)任鏈
。