偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

巧用『責任鏈模式』來優(yōu)化參數(shù)多重校驗,非常優(yōu)雅!

開發(fā) 前端
責任鏈模式是一種非常實用的設(shè)計模式,它能讓你的代碼變得更加優(yōu)雅、可維護和可擴展。在參數(shù)校驗、權(quán)限校驗、日志處理等場景中,責任鏈模式都能發(fā)揮出巨大的作用。

兄弟們,今天咱們來聊聊一個超實用的設(shè)計模式 —— 責任鏈模式。這玩意兒在參數(shù)校驗這塊兒簡直是神器,能把你從層層嵌套的 if - else 地獄里解救出來,讓代碼瞬間變得優(yōu)雅又清爽。

一、參數(shù)校驗的痛,你懂的

先問大家一個扎心的問題:你們寫代碼的時候,有沒有遇到過那種需要對參數(shù)進行 N 重校驗的情況?比如一個用戶注冊接口,要校驗用戶名是否為空、密碼長度夠不夠、郵箱格式對不對、年齡是否合法…… 這時候,你們是不是習慣性地寫成這樣:

public void register(User user) {
    if (user == null) {
        throw new IllegalArgumentException("用戶信息不能為空");
    }
    if (StringUtils.isBlank(user.getUsername())) {
        throw new IllegalArgumentException("用戶名不能為空");
    }
    if (user.getPassword().length() < 6) {
        throw new IllegalArgumentException("密碼長度不能小于6位");
    }
    if (!Pattern.matches(EMAIL_PATTERN, user.getEmail())) {
        throw new IllegalArgumentException("郵箱格式不正確");
    }
    if (user.getAge() < 18 || user.getAge() > 100) {
        throw new IllegalArgumentException("年齡必須在18到100歲之間");
    }
    // 其他業(yè)務(wù)邏輯
}

乍一看好像沒啥問題,功能也能實現(xiàn)。但是,隨著業(yè)務(wù)的發(fā)展,校驗邏輯越來越多,這代碼就會變得越來越臃腫。每次新增一個校驗條件,都得在這個方法里加一個 if 語句,代碼的可讀性和可維護性直線下降。而且,這些校驗邏輯都是硬編碼在方法里的,復(fù)用起來也很麻煩。

要是其他地方也需要類似的校驗,你就得把這段代碼復(fù)制粘貼過去,這就導(dǎo)致了代碼的重復(fù)。更要命的是,這種寫法把校驗邏輯和業(yè)務(wù)邏輯緊緊地耦合在一起。如果哪天產(chǎn)品經(jīng)理說要調(diào)整校驗順序,或者新增一個校驗條件,你就得在這個方法里改來改去,牽一發(fā)而動全身,很容易引入 bug。

二、責任鏈模式來救場

這時候,責任鏈模式就閃亮登場啦!責任鏈模式是一種行為型設(shè)計模式,它允許你將請求沿著處理者鏈進行傳遞。每個處理者都有機會處理請求,或者將請求傳遞給下一個處理者。這樣一來,請求的發(fā)送者和接收者就解耦了,而且可以動態(tài)地調(diào)整處理者鏈的順序。

1. 責任鏈模式的核心角色

  • 抽象處理者(Handler):定義了處理請求的接口,并且持有下一個處理者的引用。
  • 具體處理者(Concrete Handler):實現(xiàn)了抽象處理者的接口,具體處理請求。如果當前處理者不能處理請求,就將請求傳遞給下一個處理者。
  • 客戶端(Client):創(chuàng)建處理者鏈,并將請求發(fā)送給鏈中的第一個處理者。

2. 用責任鏈模式重構(gòu)參數(shù)校驗

咱們就拿剛才的用戶注冊參數(shù)校驗來說,用責任鏈模式重構(gòu)后,代碼會變得超級清爽。

首先,定義一個抽象處理者:

public abstract class AbstractValidator {
    protected AbstractValidator nextValidator;
    public void setNextValidator(AbstractValidator nextValidator) {
        this.nextValidator = nextValidator;
    }
    public abstract void validate(User user);
}

然后,為每個校驗條件創(chuàng)建一個具體處理者:

public class UserNullValidator extends AbstractValidator {
    @Override
    public void validate(User user) {
        if (user == null) {
            throw new IllegalArgumentException("用戶信息不能為空");
        }
        if (nextValidator != null) {
            nextValidator.validate(user);
        }
    }
}
public class UsernameValidator extends AbstractValidator {
    @Override
    public void validate(User user) {
        if (StringUtils.isBlank(user.getUsername())) {
            throw new IllegalArgumentException("用戶名不能為空");
        }
        if (nextValidator != null) {
            nextValidator.validate(user);
        }
    }
}
public class PasswordValidator extends AbstractValidator {
    @Override
    public void validate(User user) {
        if (user.getPassword().length() < 6) {
            throw new IllegalArgumentException("密碼長度不能小于6位");
        }
        if (nextValidator != null) {
            nextValidator.validate(user);
        }
    }
}
public class EmailValidator extends AbstractValidator {
    @Override
    public void validate(User user) {
        if (!Pattern.matches(EMAIL_PATTERN, user.getEmail())) {
            throw new IllegalArgumentException("郵箱格式不正確");
        }
        if (nextValidator != null) {
            nextValidator.validate(user);
        }
    }
}
public class AgeValidator extends AbstractValidator {
    @Override
    public void validate(User user) {
        if (user.getAge() < 18 || user.getAge() > 100) {
            throw new IllegalArgumentException("年齡必須在18到100歲之間");
        }
        if (nextValidator != null) {
            nextValidator.validate(user);
        }
    }
}

最后,在客戶端創(chuàng)建處理者鏈,并調(diào)用校驗方法:

public class ValidatorChain {
    public static AbstractValidator buildUserValidatorChain() {
        AbstractValidator userNullValidator = new UserNullValidator();
        AbstractValidator usernameValidator = new UsernameValidator();
        AbstractValidator passwordValidator = new PasswordValidator();
        AbstractValidator emailValidator = new EmailValidator();
        AbstractValidator ageValidator = new AgeValidator();
        userNullValidator.setNextValidator(usernameValidator);
        usernameValidator.setNextValidator(passwordValidator);
        passwordValidator.setNextValidator(emailValidator);
        emailValidator.setNextValidator(ageValidator);
        return userNullValidator;
    }
}
// 使用時
public void register(User user) {
    AbstractValidator validatorChain = ValidatorChain.buildUserValidatorChain();
    validatorChain.validate(user);
    // 其他業(yè)務(wù)邏輯
}

這樣一來,所有的校驗邏輯都被封裝到了具體的處理者中,代碼的可讀性和可維護性大大提高。而且,如果需要新增一個校驗條件,只需要創(chuàng)建一個新的具體處理者,并將其添加到處理者鏈中即可,不需要修改現(xiàn)有的代碼,完全符合開閉原則。

三、責任鏈模式的高級玩法

1. 動態(tài)調(diào)整處理者鏈

在實際開發(fā)中,有時候需要根據(jù)不同的業(yè)務(wù)場景動態(tài)調(diào)整處理者鏈的順序。比如,在某些情況下,可能需要先校驗?zāi)挲g,再校驗郵箱。這時候,責任鏈模式的靈活性就體現(xiàn)出來了。

public class DynamicValidatorChain {
    public static AbstractValidator buildDynamicValidatorChain(boolean isSpecialUser) {
        AbstractValidator userNullValidator = new UserNullValidator();
        AbstractValidator usernameValidator = new UsernameValidator();
        AbstractValidator passwordValidator = new PasswordValidator();
        AbstractValidator emailValidator = new EmailValidator();
        AbstractValidator ageValidator = new AgeValidator();
        if (isSpecialUser) {
            // 特殊用戶先校驗?zāi)挲g
            userNullValidator.setNextValidator(ageValidator);
            ageValidator.setNextValidator(usernameValidator);
            usernameValidator.setNextValidator(passwordValidator);
            passwordValidator.setNextValidator(emailValidator);
        } else {
            // 普通用戶按正常順序校驗
            userNullValidator.setNextValidator(usernameValidator);
            usernameValidator.setNextValidator(passwordValidator);
            passwordValidator.setNextValidator(emailValidator);
            emailValidator.setNextValidator(ageValidator);
        }
        return userNullValidator;
    }
}

2. 收集所有校驗錯誤

有時候,我們不希望校驗一出錯就立即拋出異常,而是希望收集所有的校驗錯誤,然后一次性返回給用戶。這時候,責任鏈模式也能輕松實現(xiàn)。

首先,定義一個校驗結(jié)果類:

public class ValidationResult {
    private boolean isValid;
    private List<String> errors;
    public ValidationResult() {
        this.isValid = true;
        this.errors = new ArrayList<>();
    }
    public void addError(String error) {
        this.isValid = false;
        this.errors.add(error);
    }
    // getter 和 setter 方法
}

然后,修改抽象處理者和具體處理者,讓它們支持收集錯誤:

public abstract class AbstractValidator {
    protected AbstractValidator nextValidator;
    public void setNextValidator(AbstractValidator nextValidator) {
        this.nextValidator = nextValidator;
    }
    public abstract void validate(User user, ValidationResult result);
}
public class UserNullValidator extends AbstractValidator {
    @Override
    public void validate(User user, ValidationResult result) {
        if (user == null) {
            result.addError("用戶信息不能為空");
        }
        if (nextValidator != null) {
            nextValidator.validate(user, result);
        }
    }
}
// 其他具體處理者類似修改

最后,在客戶端調(diào)用校驗方法并處理結(jié)果:

public void register(User user) {
    AbstractValidator validatorChain = ValidatorChain.buildUserValidatorChain();
    ValidationResult result = new ValidationResult();
    validatorChain.validate(user, result);
    if (!result.isValid()) {
        // 處理錯誤
        System.out.println("校驗失敗,錯誤信息:" + result.getErrors());
        return;
    }
    // 其他業(yè)務(wù)邏輯
}

3. 異步校驗

在某些性能敏感的場景中,可能需要對參數(shù)進行異步校驗,以提高系統(tǒng)的吞吐量。責任鏈模式也能支持異步校驗。

首先,定義一個異步處理者接口:

public interface AsyncValidator {
    CompletableFuture<ValidationResult> validateAsync(User user);
}

然后,創(chuàng)建異步處理者:

public class AsyncUserNullValidator implements AsyncValidator {
    private AsyncValidator nextValidator;

    public void setNextValidator(AsyncValidator nextValidator) {
        this.nextValidator = nextValidator;
    }

    @Override
    public CompletableFuture<ValidationResult> validateAsync(User user) {
        return CompletableFuture.supplyAsync(() -> {
            ValidationResult result = new ValidationResult();
            if (user == null) {
                result.addError("用戶信息不能為空");
            }
            if (nextValidator != null) {
                return nextValidator.validateAsync(user).join();
            }
            return result;
        });
    }
}

// 其他異步處理者類似實現(xiàn)

最后,在客戶端調(diào)用異步校驗方法:

public void register(User user) {
    AsyncValidator asyncValidatorChain = buildAsyncValidatorChain();
    asyncValidatorChain.validateAsync(user)
           .thenAccept(result -> {
                if (!result.isValid()) {
                    // 處理錯誤
                    System.out.println("異步校驗失敗,錯誤信息:" + result.getErrors());
                    return;
                }
                // 其他業(yè)務(wù)邏輯
            });
}

四、責任鏈模式的優(yōu)缺點

優(yōu)點

  1. 解耦請求與處理者:請求的發(fā)送者不需要知道具體是哪個處理者處理了請求,只需要將請求發(fā)送到鏈上即可。
  2. 提高代碼的可維護性和可擴展性:新增或修改一個處理者時,只需要修改相應(yīng)的處理者類,不需要修改其他代碼。
  3. 動態(tài)調(diào)整處理順序:可以根據(jù)不同的業(yè)務(wù)場景動態(tài)調(diào)整處理者鏈的順序。
  4. 支持多種校驗結(jié)果處理方式:可以選擇立即拋出異常,也可以收集所有錯誤后一次性返回。

缺點

  1. 性能問題:如果處理者鏈很長,請求在鏈上傳遞的時間可能會比較長,影響系統(tǒng)性能。
  2. 調(diào)試困難:由于請求是沿著鏈傳遞的,調(diào)試時可能需要跟蹤多個處理者的執(zhí)行情況。
  3. 請求可能未被處理:如果處理者鏈中沒有任何一個處理者能夠處理請求,那么請求可能會被忽略。

五、責任鏈模式的應(yīng)用場景

  1. 參數(shù)校驗:這是責任鏈模式最常見的應(yīng)用場景,能有效避免層層嵌套的 if - else 語句。
  2. 權(quán)限校驗:比如在一個系統(tǒng)中,不同級別的用戶有不同的操作權(quán)限,可以使用責任鏈模式來校驗用戶的權(quán)限。
  3. 日志處理:不同級別的日志(如 DEBUG、INFO、WARN、ERROR)可以由不同的處理者來處理。
  4. 過濾器鏈:在 Web 開發(fā)中,過濾器鏈(如 Servlet 過濾器)就是責任鏈模式的典型應(yīng)用。
  5. 工作流引擎:工作流中的各個審批環(huán)節(jié)可以看作是責任鏈中的處理者。

六、總結(jié)

責任鏈模式是一種非常實用的設(shè)計模式,它能讓你的代碼變得更加優(yōu)雅、可維護和可擴展。在參數(shù)校驗、權(quán)限校驗、日志處理等場景中,責任鏈模式都能發(fā)揮出巨大的作用。當然,責任鏈模式也有一些缺點,比如性能問題和調(diào)試困難,但只要在使用時注意這些問題,就能充分發(fā)揮它的優(yōu)勢。

責任編輯:武曉燕 來源: 石杉的架構(gòu)筆記
相關(guān)推薦

2023-03-28 08:07:12

2022-05-03 10:43:43

SpringJava

2021-12-24 07:50:45

責任鏈模式設(shè)計

2022-12-28 08:08:57

2012-03-28 13:28:56

Java設(shè)計模式

2011-07-25 18:03:12

組策略

2024-12-03 15:52:45

責任鏈Java

2022-11-01 08:46:20

責任鏈模式對象

2010-04-01 09:10:03

PHP設(shè)計模式責任鏈模式

2021-07-14 10:08:30

責任鏈模式加工鏈

2024-01-30 13:15:00

設(shè)計模式責任鏈

2025-07-29 02:15:00

2021-06-05 17:59:00

責任鏈模式設(shè)計

2023-09-28 08:45:56

開源責任鏈模式

2024-06-04 13:11:52

Python行為設(shè)計模式開發(fā)

2023-09-26 00:27:07

設(shè)計模式鏈接

2021-05-25 09:00:52

責任鏈模式設(shè)計模式面試經(jīng)歷

2023-06-05 07:55:31

2023-11-29 07:23:04

參數(shù)springboto

2020-11-17 09:32:57

設(shè)計模式責任鏈
點贊
收藏

51CTO技術(shù)棧公眾號