這里我們使用責任鏈模式來創建一個參數校驗的示例。在這個示例中,我們將實現一個簡單的責任鏈來校驗不同的參數條件。這種模式允許我們將多個校驗步驟串聯在一起,以便可以在不同的條件下進行靈活的校驗。
設計思路
-
接口定義 (
Validator
)- 目的:定義責任鏈中每個節點的基本行為。
- 設計思想:接口包含三個方法:
Validate(params *Params) error
:執行具體的校驗邏輯。SetNext(v Validator) Validator
:設置鏈中的下一個校驗節點,實現鏈式調用。Execute(params *Params) error
:執行當前節點的Validate
方法,并繼續執行鏈中的下一個節點。
-
復用機制 (
BaseValidator
)- 目的:通過合成復用來實現校驗鏈的連接機制。
- 設計思想:
BaseValidator
是一個可復用的結構體,包含nextValidator
字段(用于指向鏈中的下一個校驗節點)和實現SetNext
、Execute
方法。任何實現了Validator
接口的結構體都可以通過嵌入BaseValidator
來獲得這些方法。
-
具體校驗器
- 目的:每個校驗器負責校驗請求中的某一特定參數。
- 設計思想:
- 例如,
NonEmptyValidator
用于檢查字符串是否為空,PositiveNumberValidator
用于檢查數字是否為正。 - 這些校驗器通過嵌入
BaseValidator
來獲得鏈式調用的能力。
- 例如,
-
鏈式調用
- 目的:通過鏈式調用初始化責任鏈,使代碼結構清晰,增強可讀性。
- 設計思想:通過
SetNext
方法將各個校驗器連接起來,使得責任鏈的邏輯關系一目了然。
-
擴展性
- 目的:輕松擴展系統功能,支持更多的校驗邏輯。
- 設計思想:由于責任鏈是動態配置的,可以方便地添加、移除或重排校驗器節點,而無需修改現有代碼結構。
案例代碼
以下是一個基于責任鏈模式的參數校驗示例:
package mainimport ("errors""fmt"
)// Validator 接口定義了校驗器的基本行為
type Validator interface {Validate(params *Params) errorSetNext(v Validator) ValidatorExecute(params *Params) error
}// BaseValidator 復用結構體,實現 Validator 接口的 SetNext 和 Execute 方法
type BaseValidator struct {nextValidator Validator
}// SetNext 設置下一個校驗器
func (b *BaseValidator) SetNext(v Validator) Validator {b.nextValidator = vreturn v
}// Execute 執行當前校驗和后續校驗
func (b *BaseValidator) Execute(params *Params) error {if b.nextValidator != nil {if err := b.nextValidator.Validate(params); err != nil {return err}return b.nextValidator.Execute(params)}return nil
}// Params 結構體包含需要校驗的參數
type Params struct {Name stringAge intEmail string
}// NonEmptyValidator 校驗字符串是否為空
type NonEmptyValidator struct {BaseValidator
}func (v *NonEmptyValidator) Validate(params *Params) error {if params.Name == "" {return errors.New("name cannot be empty")}return nil
}// PositiveNumberValidator 校驗數字是否為正
type PositiveNumberValidator struct {BaseValidator
}func (v *PositiveNumberValidator) Validate(params *Params) error {if params.Age <= 0 {return errors.New("age must be a positive number")}return nil
}// EmailFormatValidator 校驗郵件格式(簡單示例)
type EmailFormatValidator struct {BaseValidator
}func (v *EmailFormatValidator) Validate(params *Params) error {if params.Email == "" || !contains(params.Email, "@") {return errors.New("invalid email format")}return nil
}// contains 是一個簡單的字符串包含判斷函數
func contains(s, substr string) bool {return len(s) >= len(substr) && (s[:len(substr)] == substr || contains(s[1:], substr))
}func main() {params := &Params{Name: "John Doe",Age: 30,Email: "johndoe@example.com",}// 初始化校驗鏈validator := &NonEmptyValidator{}validator.SetNext(&PositiveNumberValidator{}).SetNext(&EmailFormatValidator{})// 執行校驗err := validator.Execute(params)if err != nil {fmt.Println("Validation failed:", err)} else {fmt.Println("Validation succeeded")}
}