引言?
在當今的軟件開發領域,Spring Boot 以其高效、便捷的特性成為構建 Java 應用程序的熱門框架。而設計模式作為軟件開發中的寶貴經驗總結,能夠顯著提升代碼的可維護性、可擴展性和可復用性。本文將深入探討幾種常用設計模式在 Spring Boot 項目中的實際應用,通過具體案例幫助讀者更好地理解和掌握這些設計模式在實際開發中的運用技巧。
一、工廠模式
場景描述?
假設我們正在開發一個電商系統,其中有多種不同類型的訂單,如普通訂單、促銷訂單、團購訂單等。每種訂單在處理時都有一些獨特的邏輯,例如促銷訂單需要計算優惠金額,團購訂單需要處理成團邏輯等。我們可以使用工廠模式來根據訂單類型創建不同的訂單處理對象。?
代碼實現
1.定義訂單處理接口
public interface OrderProcessor {void processOrder(); }
2.創建具體的訂單處理類
- 普通訂單處理類
@Component public class NormalOrderProcessor implements OrderProcessor {@Overridepublic void processOrder() {System.out.println("Processing normal order...");} }
- 促銷訂單處理類
@Component public class PromotionOrderProcessor implements OrderProcessor {@Overridepublic void processOrder() {System.out.println("Processing promotion order, calculating discounts...");} }
3.創建訂單工廠類
@Component public class OrderFactory {@Autowiredprivate Map<String, OrderProcessor> orderProcessorMap;public OrderProcessor getOrderProcessor(String orderType) {return orderProcessorMap.get(orderType);} }
4.在服務層使用工廠類
@Service public class OrderService {@Autowiredprivate OrderFactory orderFactory;public void process(String orderType) {OrderProcessor orderProcessor = orderFactory.getOrderProcessor(orderType);if (orderProcessor != null) {orderProcessor.processOrder();} else {System.out.println("No suitable order processor found for type: " + orderType);}} }
優勢分析?
通過工廠模式,我們將對象的創建和使用分離,當需要新增訂單類型時,只需創建新的訂單處理類并在配置中注冊,無需修改大量現有代碼,提高了系統的可擴展性。?
二、單例模式?
場景描述?
在 Spring Boot 項目中,經常會有一些資源或對象只需要一個實例,例如數據庫連接池、日志記錄器等。以日志記錄器為例,我們希望整個應用程序中只有一個日志記錄器實例,以確保日志記錄的一致性和高效性。?
代碼實現
1.使用 Spring 的注解實現單例
@Component public class CustomLogger {private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CustomLogger.class);public void logMessage(String message) {logger.info(message);} }
在 Spring 中,默認情況下,通過@Component注解創建的 Bean 就是單例模式。當其他組件需要使用CustomLogger時,直接注入即可。
@Service public class SomeService {@Autowiredprivate CustomLogger customLogger;public void doSomething() {customLogger.logMessage("Service is doing something...");} }
優勢分析?
單例模式確保了系統中特定資源或對象的唯一性,避免了資源的重復創建和浪費,提高了系統性能和資源利用率,同時也方便了對共享資源的管理和維護。?
三、代理模式?
場景描述?
假設我們有一個業務方法,在調用該方法前后需要添加一些通用的邏輯,比如權限驗證、日志記錄等。我們可以使用代理模式來實現這些橫切關注點,而無需在每個業務方法中重復編寫相同的代碼。?
代碼實現
1.定義業務接口
public interface UserService {void doBusinessLogic(); }
2.創建真實業務類
@Service public class UserServiceImpl implements UserService {@Overridepublic void doBusinessLogic() {System.out.println("Doing business logic...");} }
3.創建代理類
@Aspect @Component public class UserServiceProxy {@Around("execution(* com.example.demo.service.UserService.doBusinessLogic(..))")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("Before business logic - checking permissions");Object result = joinPoint.proceed();System.out.println("After business logic - logging");return result;} }
優勢分析?
代理模式將核心業務邏輯與輔助性的橫切邏輯分離,使代碼更加清晰、可維護。通過代理類,我們可以方便地在不修改原有業務代碼的基礎上添加新的功能,符合開閉原則。
四、策略模式?
場景描述?
繼續以電商系統為例,系統中有多種不同的運費計算方式,如按重量計算、按訂單金額計算、固定運費等。為了能夠靈活地切換和管理這些運費計算方式,我們可以運用策略模式。?
代碼實現
1.定義運費計算策略接口
public interface ShippingFeeStrategy {double calculateShippingFee(double weight, double orderAmount); }
2.創建具體的運費計算策略類
- 按重量計算運費策略類
@Component public class WeightBasedShippingStrategy implements ShippingFeeStrategy {@Overridepublic double calculateShippingFee(double weight, double orderAmount) {// 假設每千克運費為10元return weight * 10;} }
- 按訂單金額計算運費策略類
@Component public class OrderAmountBasedShippingStrategy implements ShippingFeeStrategy {@Overridepublic double calculateShippingFee(double weight, double orderAmount) {// 假設訂單金額滿100免運費,否則收取10元運費return orderAmount >= 100? 0 : 10;} }
- 固定運費策略類
@Component public class FixedShippingStrategy implements ShippingFeeStrategy {@Overridepublic double calculateShippingFee(double weight, double orderAmount) {// 固定運費為5元return 5;} }
3.創建運費計算服務,使用策略模式
@Service public class ShippingFeeService {@Autowiredprivate Map<String, ShippingFeeStrategy> shippingFeeStrategyMap;public double calculate(String strategyType, double weight, double orderAmount) {ShippingFeeStrategy strategy = shippingFeeStrategyMap.get(strategyType);if (strategy != null) {return strategy.calculateShippingFee(weight, orderAmount);} else {throw new IllegalArgumentException("No suitable shipping fee strategy found for type: " + strategyType);}} }
優勢分析?
策略模式使得不同的運費計算算法可以獨立變化,符合開閉原則。當需要新增運費計算方式時,只需創建新的策略類并實現接口,然后在配置中注冊即可,無需修改現有業務代碼,大大提高了系統的靈活性和可維護性。同時,不同的策略類可以被復用,提高了代碼的復用性。
補充
也可以自定義Match接口實現策略模式,大致思路如下:
1.定義Match接口
public interface Match<T> {boolean match(T var1); }
2.業務接口繼承Match接口
public interface BusinessHandler extends Match<String> {/*** 業務執行方法** @param context 上下文*/void execute(BusinessContext context); }
3.特定策略類實現業務接口
類一:
@Slf4j @Component public class ExactMatchSort implements BusinessHandler {@Setter(onMethod_ = @Autowired)BusinessService businessService;/*** {@inheritDoc}*/@Overridepublic boolean match(String value) {return RuleEnum.EXACT_MATCH.getCode().equals(value);}/*** {@inheritDoc}*/@Overridepublic void execute(BusinessContext context) {// 自定義業務邏輯businessService.exactMatch(context);} }
類二:
@Slf4j @Component public class FuzzyMatchSort implements BusinessHandler {@Setter(onMethod_ = @Autowired)BusinessService businessService;/*** {@inheritDoc}*/@Overridepublic boolean match(String value) {return RuleEnum.FUZZY_MATCH.getCode().equals(value);}/*** {@inheritDoc}*/@Overridepublic void execute(BusinessContext context) {// 自定義業務邏輯businessService.fuzzyMatch(context);} }
4.定義抽象策略管理器
public abstract class AbstractProcessorManage<T, P extends Match<T>> {private List<P> processorList;public AbstractProcessorManage() {}@Autowiredpublic void setProcessorList(List<P> processorList) {this.processorList = processorList;}public abstract String getCannotMatchMessage();public P getProcessor(T t) {for(P p : this.processorList) {if (p.match(t)) {return p;}}throw new RuntimeException(this.getCannotMatchMessage());} }
5.定義業務策略管理器
/*** 策略管理器*/ @Component public class BusinessManger extends AbstractProcessorManage<String, BusinessHandler> {/*** {@inheritDoc}*/@Overridepublic String getCannotMatchMessage() {return "非法的策略";} }
6.業務流程調用
/*** 業務執行類**/ @Slf4j @Component public class StockFilterManager {@Setter(onMethod_ = @Autowired)private BusinessManger businessManger;private void businessExcute(BusinessContext context) {businessManger.getProcessor(context.value).execute(context);} }
這僅是基礎架構,也可以在內層嵌套更多的設計模式,以保證代碼的可讀性與可維護性。
結論
通過以上在 Spring Boot 項目中的實戰案例,我們看到了工廠模式、單例模式、代理模式以及策略模式在不同場景下的應用及其帶來的顯著優勢。在實際項目開發中,合理運用設計模式能夠極大地提升代碼質量,使項目更加健壯、靈活和易于維護。希望讀者通過本文的學習,能夠在自己的 Spring Boot 項目中熟練運用這些設計模式,打造出更優秀的軟件系統。