mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
feature: design patter
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
## 妙用设计模式来设计一个客户端校验器
|
||||
|
||||
> 订单在提交的时候会面临不同的校验规则,不同的校验规则会有不同的处理。假设这个处理就是弹窗。
|
||||
>
|
||||
> 有的时候会命中规则1,则弹窗1,有的时候同时命中规则1、2、3,但由于存在规则的优先级,则会处理优先级最高的弹窗1。
|
||||
>
|
||||
> 老的业务背景下,弹窗优先级或者说校验规则是统一的。直接用函数翻译实现,写多个 if 问题不大。
|
||||
>
|
||||
> 但在新业务背景下,不同的条件,弹窗优先级不一致,之前的写法需要写大量的嵌套判断,代码难以维护。
|
||||
>
|
||||
> 所以问题抽象为:如何设计一个校验器
|
||||
|
||||
> 业务逻辑千变万化,弹窗优先级不断改变,代码冗余问题和难以维护问题如何解决?
|
||||
> 本篇文章从设计模式角度出发,讨论责任链设计模式和工厂设计模式2个方式,如何去设计一个校验器,同时解决代码冗余和难以维护的问题
|
||||
|
||||
|
||||
## 问题背景
|
||||
|
||||
订单在提交的时候会面临不同的校验规则,不同的校验规则会有不同的处理。假设这个处理就是弹窗。
|
||||
有的时候会命中规则1,则弹窗1,有的时候同时命中规则1、2、3,但由于存在规则的优先级,则会处理优先级最高的弹窗1。
|
||||
|
||||
老的业务背景下,弹窗优先级或者说校验规则是统一的。直接用函数翻译实现,写多个 if 问题不大。
|
||||
但在新业务背景下,不同的条件,弹窗优先级不一致,之前的写法需要写大量的嵌套判断,代码难以维护。
|
||||
|
||||
所以问题抽象为:如何设计一个校验器
|
||||
|
||||
|
||||
为了清晰说明问题,假设线上的弹窗校验规则为:A -> B -> C
|
||||
|
||||
```Plain
|
||||
@@ -193,7 +195,7 @@ Node 洋葱模式:发送一个 Request 一层层中间件去处理,比如添
|
||||
采用责任链设计模式。基类 `OrderSubmitBaseValidator` 声明接口,是一个抽象类:
|
||||
|
||||
- 有一个属性 `nextValidator` 用于指向下一个校验器
|
||||
- 有一个方法 `- (void)validate:(id)params;` 用于处理校验,内部默认实现是传递给下一个校验器。
|
||||
- 有一个方法 `- (void)validate:(id)params;` 用于处理校验,内部利用模版模式,默认实现是传递给下一个校验器
|
||||
|
||||
```Shell
|
||||
//.h
|
||||
@@ -294,7 +296,7 @@ let validateType = [OrderSubmitValidator generateTypeWithParams:params];
|
||||
[OrderSubmitValidator validateWith:validateType];
|
||||
```
|
||||
|
||||
`validateWith` 方法内部根据 validateType 去组装 Map 的 key,然后从 Map 中取出具体规则组合,然后依次迭代遍历执行
|
||||
利用策略模式 `validateWith` 方法内部根据 validateType 去组装 Map 的 key,然后从 Map 中取出具体规则组合,然后依次迭代遍历执行
|
||||
|
||||
```
|
||||
let rulesMap = {
|
||||
@@ -303,13 +305,16 @@ let rulesMap = {
|
||||
!isVIP: [a-c-d-b],
|
||||
}
|
||||
```
|
||||
这部分策略的生成也可以单独抽取出去,比如 ValidateStrategyFactory 去根据不同的信息,生成不同的策略。
|
||||
|
||||
优点:
|
||||
|
||||
1. 解决了现在的错误弹窗的隐含逻辑,后续人接手,弹窗优先级清晰可见,提高可维护性,减少出错概率
|
||||
2. 对于判断(校验)的增减都无需关心其他的校验规则。类似维护链表,仅在一开始指定即可,符合“开闭原则
|
||||
2. 对于判断(校验)的增减都无需关心其他的校验规则。类似维护链表,仅在一开始指定即可,符合“开闭原则”
|
||||
3. 对于现有校验规则的修改足够收口,每个规则都有自己的 validator 和 validate 方法
|
||||
4. 目前弹窗优先级针对 EVA 、BTC 存在不同优先级顺序,如果按照现有的方案实施,则会存在很多冗余代码
|
||||
4. 目前弹窗优先级针对 isVIP、isCharged 存在不同优先级顺序,如果按照现有的方案实施,则会存在很多冗余代码
|
||||
5. 按照策略模式,不同的校验规则,组装不同的策略,也可以单独抽取出去,独立维护,更清晰
|
||||
6. validate 内部按照模版模式,调用 `isValidate` 方法,每个单独的 Validator 不需要额外去调用 next,设计更加健壮,防止别人漏写
|
||||
|
||||
|
||||
|
||||
@@ -396,5 +401,5 @@ OrderSumitValidatorFactory {
|
||||
- 优先级的关系维护在不同的子类中,各司其职,独立维护
|
||||
|
||||
|
||||
最后选什么?组合优于继承,个人倾向使用责任链模式去组织代码。关于责任链设计模式的文章也可以看这篇[文章](./../Chapter6%20-%20Design%20Pattern/6.23.md)
|
||||
|
||||
最后选什么?组合优于继承,个人倾向使用责任链模式去组织代码。
|
||||
|
||||
@@ -32,8 +32,12 @@
|
||||
```
|
||||
|
||||
### 类别的作用
|
||||
|
||||
拓展当前类,为类添加方法
|
||||
可以把类的实现分开在几个不同的源文件里,所以好处是:
|
||||
- 减少耽搁文件的代码行数
|
||||
- 可以把不痛的功能组织到不同的 category 里
|
||||
- 可以由多个开发者共同完成一个大的类,方便协作
|
||||
- 拓展当前类,为类添加方法
|
||||
- 声明私有方法
|
||||
|
||||
### 类别的局限性
|
||||
|
||||
|
||||
Reference in New Issue
Block a user