最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在SpringBoot項目中策略模式的使用方式

 更新時間:2026年01月20日 09:21:26   作者:L_!?。? 
本文介紹了如何使用策略模式和Spring依賴注入來優(yōu)化一個更新考試信息的方法,通過策略模式,每個更新邏輯被封裝在獨立的策略類中,并且可以通過Spring的依賴注入機制自動管理策略的選擇和執(zhí)行順序,這種方式使得代碼更加解耦、可擴展和維護性好

使用策略模式之前的代碼

 @Override
    public void updateExam(String id, ExamUpdateDTO examUpdateDTO) {
        logger.info("Service: 修改考試場次, ID: {}, 數(shù)據(jù): {}", id, examUpdateDTO);

        Exam existingExam = mongoDBUtils.findById(id, Exam.class);
        if (existingExam == null) {
            throw new EntityNotFoundException("考試場次不存在: " + id);
        }

        Map<String, Object> examUpdateMap = new HashMap<>();
        if (examUpdateDTO.getExamName() != null) {
            examUpdateMap.put("examName", examUpdateDTO.getExamName());
        }
        if (examUpdateDTO.getExamDescription() != null) {
            examUpdateMap.put("examDescription", examUpdateDTO.getExamDescription());
        }
        if (examUpdateDTO.getStartTime() != null) {
            examUpdateMap.put("startTime", examUpdateDTO.getStartTime());
        }
        if (examUpdateDTO.getDuration() != null) {
            examUpdateMap.put("duration", examUpdateDTO.getDuration());
        }
        if (examUpdateDTO.getStatus() != null) {
            examUpdateMap.put("status", examUpdateDTO.getStatus());
        }

        if (examUpdateMap.isEmpty()) {
            logger.warn("Service: 沒有可更新的考試場次字段, ID: {}", id);
            return;
        }
        
        examUpdateMap.put("updateTime", System.currentTimeMillis());

        boolean examUpdated = mongoDBUtils.updateOne(Criteria.where("ID").is(id), examUpdateMap, Exam.class);

        if (!examUpdated) {
            logger.warn("Service: 更新考試場次失敗 or no changes made, ID: {}", id);
        }
        logger.info("Service: 考試場次基礎(chǔ)信息更新已提交, ID: {}", id);

        boolean needsStudentUpdate = examUpdateDTO.getStartTime() != null || examUpdateDTO.getDuration() != null;

        if (needsStudentUpdate) {
            Map<String, Object> studentUpdateMap = new HashMap<>();
            if (examUpdateDTO.getStartTime() != null) {
                studentUpdateMap.put("startTime", examUpdateDTO.getStartTime());
            }
            if (examUpdateDTO.getDuration() != null) {
                studentUpdateMap.put("duration", examUpdateDTO.getDuration());
            }

            if (!studentUpdateMap.isEmpty()) {
                Criteria studentCriteria = Criteria.where("examID").is(id);
                boolean studentsUpdated = mongoDBUtils.updateMany(studentCriteria, studentUpdateMap, CompetitionSignUpLog.class);
                if (studentsUpdated) {
                    logger.info("Service: 成功級聯(lián)更新考試場次 ID {} 下學員的 startTime/duration.", id);
                } else {
                    logger.warn("Service: 級聯(lián)更新考試場次 ID {} 下學員的 startTime/duration 操作未被確認或無匹配學員.", id);
                }
            }
        }
    }

創(chuàng)建策略接口即策略實現(xiàn)類

/**
 * 更新考試場次信息的策略接口
 */
public interface UpdateExamStrategy {
    /**
     * 根據(jù)DTO將待更新的字段填充到相應(yīng)的map中。
     *
     * @param existingExam   當前的考試實體 (可用于比較或特定邏輯)
     * @param dto            考試更新DTO
     * @param examUpdateMap  用于收集考試實體自身更新的字段
     * @param studentUpdateMap 用于收集需要級聯(lián)更新到學員報名記錄的字段
     */
    void applyUpdate(Exam existingExam, ExamUpdateDTO dto, Map<String, Object> examUpdateMap, Map<String, Object> studentUpdateMap);
} 
@Component
public class ExamDescriptionUpdateStrategy implements UpdateExamStrategy {
    @Override
    public void applyUpdate(Exam existingExam, ExamUpdateDTO dto, Map<String, Object> examUpdateMap, Map<String, Object> studentUpdateMap) {
        if (dto.getExamDescription() != null) {
            examUpdateMap.put("examDescription", dto.getExamDescription());
        }
    }
}
@Component
public class ExamDurationUpdateStrategy implements UpdateExamStrategy {
    @Override
    public void applyUpdate(Exam existingExam, ExamUpdateDTO dto, Map<String, Object> examUpdateMap, Map<String, Object> studentUpdateMap) {
        if (dto.getDuration() != null) {
            examUpdateMap.put("duration", dto.getDuration());
            studentUpdateMap.put("duration", dto.getDuration()); // Also update for students
        }
    }
} ```

```java
@Component
public class ExamNameUpdateStrategy implements UpdateExamStrategy {
    @Override
    public void applyUpdate(Exam existingExam, ExamUpdateDTO dto, Map<String, Object> examUpdateMap, Map<String, Object> studentUpdateMap) {
        if (dto.getExamName() != null) {
            examUpdateMap.put("examName", dto.getExamName());
        }
    }
} 
@Component
public class ExamStartTimeUpdateStrategy implements UpdateExamStrategy {
    @Override
    public void applyUpdate(Exam existingExam, ExamUpdateDTO dto, Map<String, Object> examUpdateMap, Map<String, Object> studentUpdateMap) {
        if (dto.getStartTime() != null) {
            examUpdateMap.put("startTime", dto.getStartTime());
            studentUpdateMap.put("startTime", dto.getStartTime()); // Also update for students
        }
    }
} 
@Component
public class ExamStatusUpdateStrategy implements UpdateExamStrategy {
    @Override
    public void applyUpdate(Exam existingExam, ExamUpdateDTO dto, Map<String, Object> examUpdateMap, Map<String, Object> studentUpdateMap) {
        if (dto.getStatus() != null) {
            examUpdateMap.put("status", dto.getStatus());
        }
    }
}

使用策略模式之后的updateExam方法

@Service
public class ExamServiceImpl implements ExamService {

    private static final Logger logger = LogManager.getLogger(ExamServiceImpl.class);

    @Autowired
    private MongoDBUtils mongoDBUtils;

    private final List<UpdateExamStrategy> updateExamStrategies;

    @Autowired
    public ExamServiceImpl(MongoDBUtils mongoDBUtils, List<UpdateExamStrategy> updateExamStrategies) {
        this.mongoDBUtils = mongoDBUtils; // Ensure mongoDBUtils is assigned if it's not already via @Autowired field injection
        this.updateExamStrategies = updateExamStrategies;
    }
    //...省略其他方法的實現(xiàn)
    @Override
    public void updateExam(String id, ExamUpdateDTO examUpdateDTO) {
        logger.info("Service: 修改考試場次, ID: {}, 數(shù)據(jù): {}", id, examUpdateDTO);

        Exam existingExam = mongoDBUtils.findById(id, Exam.class);
        if (existingExam == null) {
            throw new EntityNotFoundException("考試場次不存在: " + id);
        }

        Map<String, Object> examUpdateMap = new HashMap<>();
        Map<String, Object> studentUpdateMap = new HashMap<>();

        // 遍歷所有策略并應(yīng)用更新
        for (UpdateExamStrategy strategy : updateExamStrategies) {
            strategy.applyUpdate(existingExam, examUpdateDTO, examUpdateMap, studentUpdateMap);
        }

        if (!examUpdateMap.isEmpty()) {
            examUpdateMap.put("updateTime", System.currentTimeMillis());
            boolean examUpdated = mongoDBUtils.updateOne(Criteria.where("ID").is(id), examUpdateMap, Exam.class);
            if (!examUpdated) {
                logger.warn("Service: 更新考試場次失敗 or no changes made, ID: {}", id);
            } else {
                logger.info("Service: 考試場次基礎(chǔ)信息更新已提交, ID: {}", id);
            }
        } else {
            logger.info("Service: 沒有可更新的考試場次字段, ID: {}", id);
            // 如果 examUpdateMap 為空,但 studentUpdateMap 不為空,則不需要返回
            // 即使考試本身沒有變化,關(guān)聯(lián)的學生信息可能仍需更新
        }

        if (!studentUpdateMap.isEmpty()) {
            Criteria studentCriteria = Criteria.where("examID").is(id);
            boolean studentsUpdated = mongoDBUtils.updateMany(studentCriteria, studentUpdateMap, CompetitionSignUpLog.class);
            if (studentsUpdated) {
                logger.info("Service: 成功級聯(lián)更新考試場次 ID {} 下學員的相關(guān)信息.", id);
            } else {
                logger.warn("Service: 級聯(lián)更新考試場次 ID {} 下學員信息的操作未被確認或無匹配學員.", id);
            }
        }
    }
 }   

在這個場景中,策略的選擇是由Spring的依賴注入機制自動完成的。

具體工作原理:

1、策略的收集

  • 由于每個策略類(如ExamDescriptionUpdateStrategy、ExamStatusUpdateStrategyExamStartTimeUpdateStrategy)都標注了@Component注解
  • Spring會自動掃描并實例化這些實現(xiàn)了UpdateExamStrategy接口的類
  • 所有策略實例會被自動注入到ExamServiceImpl中的updateExamStrategies列表中

2、策略的順序

Spring在注入時會按照以下規(guī)則確定策略在列表中的順序:

  • 默認按照類名的字母順序
  • 可以通過@Order注解或?qū)崿F(xiàn)Ordered接口來自定義順序

3、策略的使用

@Autowired
public ExamServiceImpl(MongoDBUtils mongoDBUtils, List<UpdateExamStrategy> updateExamStrategies) {
    this.mongoDBUtils = mongoDBUtils;
    this.updateExamStrategies = updateExamStrategies;  // Spring自動注入所有策略
}

4、遍歷執(zhí)行

for (UpdateExamStrategy strategy : updateExamStrategies) {
    strategy.applyUpdate(existingExam, examUpdateDTO, examUpdateMap, studentUpdateMap);
}
  • 每次遍歷會取出列表中的一個策略實例
  • 每個策略實例都是一個具體的策略類的對象(如ExamDescriptionUpdateStrategy的實例)
  • 調(diào)用策略的applyUpdate方法時,會執(zhí)行對應(yīng)策略類中的具體實現(xiàn)

這是一個典型的策略模式結(jié)合Spring依賴注入的應(yīng)用,它的好處是:

  • 解耦:各個更新策略相互獨立
  • 可擴展:添加新的更新策略只需創(chuàng)建新的策略類并添加@Component注解
  • 維護性好:每個策略類負責處理特定的更新邏輯

總結(jié)

這里添加了一個構(gòu)造函數(shù)來注入 mongoDBUtils 和 updateExamStrategies。如果你的項目中 mongoDBUtils 已經(jīng)通過字段上的 @Autowired 注入,那么在構(gòu)造函數(shù)中再次賦值是多余的,但通常無害。Spring 的依賴注入會處理好這些。

主要邏輯已更改為: 初始化 examUpdateMap 和 studentUpdateMap。 遍歷所有注入的 UpdateExamStrategy 策略。 每個策略根據(jù) ExamUpdateDTO 的內(nèi)容,決定是否要向 examUpdateMap(用于更新 Exam 實體本身)或 studentUpdateMap(用于級聯(lián)更新 CompetitionSignUpLog 實體)添加鍵值對。

如果 examUpdateMap 不為空,則更新 Exam 實體。 如果 studentUpdateMap 不為空,則更新相關(guān)的CompetitionSignUpLog 實體。

這種方式將每個字段的更新邏輯(包括是否需要級聯(lián)更新)封裝在各自的策略類中,使得 updateExam 方法本身更加簡潔,并且易于擴展新的更新邏輯。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 超級好用的輕量級JSON處理命令jq(最新推薦)

    超級好用的輕量級JSON處理命令jq(最新推薦)

    jq是一個輕量級的命令行工具,讓你可以非常方便地處理JSON數(shù)據(jù),如切分、過濾、映射、轉(zhuǎn)化等,就像sed、awk、grep文本處理三劍客一樣,這篇文章主要介紹了超級好用的輕量級JSON處理命令jq,需要的朋友可以參考下
    2023-01-01
  • 如何在Netty中注解使用Service或者Mapper

    如何在Netty中注解使用Service或者Mapper

    這篇文章主要介紹了如何在Netty中注解使用Service或者Mapper,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java8實現(xiàn)Stream流的合并的方法展示

    Java8實現(xiàn)Stream流的合并的方法展示

    本文介紹了Java8中Stream流的合并方法,包括concat()、flatMap()和reduce()三種方法。其中,concat()方法可以將兩個Stream流合并成一個,flatMap()方法可以將一個Stream流中的元素映射成多個Stream流并合并成一個,reduce()方法可以將Stream流中的元素逐個合并成一個結(jié)果
    2023-05-05
  • Spring Validation和Hibernate Validator結(jié)合國際化代碼實例

    Spring Validation和Hibernate Validator結(jié)合國際化代碼實例

    這篇文章主要介紹了Spring Validation和Hibernate Validator結(jié)合國際化代碼實例,我們需要對請求參數(shù)進行非空、長度、正確性進行校驗, 本文主要講解Spring Validation 和 Hibernate Validator, 同時整合i18n(國際化)實現(xiàn)參數(shù)校驗自動,需要的朋友可以參考下
    2023-10-10
  • Intellij IDEA安裝lombok插件及使用詳解

    Intellij IDEA安裝lombok插件及使用詳解

    今天小編就為大家分享一篇關(guān)于Intellij IDEA安裝lombok插件及使用詳解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):線性表

    java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):線性表

    這篇文章主要介紹了Java的數(shù)據(jù)解構(gòu)基礎(chǔ),希望對廣大的程序愛好者有所幫助,同時祝大家有一個好成績,需要的朋友可以參考下,希望能給你帶來幫助
    2021-07-07
  • AQS同步組件Semaphore信號量案例剖析

    AQS同步組件Semaphore信號量案例剖析

    這篇文章主要為大家介紹了AQS同步組件Semaphore信號量案例剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Java在枚舉類型中增加自定義方法詳解

    Java在枚舉類型中增加自定義方法詳解

    這篇文章主要介紹了Java在枚舉類型中增加自定義方法詳解,對于枚舉類型來說,除了無法繼承它以外,基本可以將它看作一個普通的類,這意味著你可以在里面增加自定義的方法,甚至可以增加一個 main() 方法,需要的朋友可以參考下
    2023-11-11
  • java8新特性 獲取list某一列的操作

    java8新特性 獲取list某一列的操作

    這篇文章主要介紹了java8新特性 獲取list某一列的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Spring獲取Cookie和Session(@CookieValue()和@SessionAttribute())

    Spring獲取Cookie和Session(@CookieValue()和@SessionAttribute())

    本文主要介紹了Spring獲取Cookie和Session(@CookieValue()和@SessionAttribute()),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-01-01

最新評論

滕州市| 西乌珠穆沁旗| 和顺县| 古蔺县| 浦东新区| 琼海市| 城口县| 金寨县| 吉木乃县| 嘉祥县| 奎屯市| 关岭| 天等县| 治县。| 南昌县| 邢台县| 长沙县| 澄城县| 巧家县| 萍乡市| 浦县| 镇原县| 呈贡县| 浮梁县| 余干县| 班玛县| 泰来县| 英德市| 醴陵市| 巴马| 晴隆县| 潮安县| 江陵县| 永安市| 克山县| 湛江市| 诏安县| 宣城市| 怀宁县| 宁河县| 鹰潭市|