关于android:如何优雅的在业务中使用设计模式代码如诗

2次阅读

共计 13048 个字符,预计需要花费 33 分钟才能阅读完成。

前言

有段时间没写文章了,最近沉迷 Rust,无法自拔,锈儿有毒;这真是门十分乏味的语言,很多中央的设计,真的是满足了我所有的向往。

当然,这也不是一门简略的语言,提出所有权的概念,引入了极多符号:mut、&mut、ref mut、&、*、as_mut、as_ref。。。让人头秃。。。

之前看到过一句话,感觉很不错: 学习 Rust 并不会给你带来智商上的自卑感,但或者会让你从新爱上编程。

大家如果浏览过一些开源框架的源码,可能会发现其中数不尽的抽象类,设计模式拈手而来,在性能框架中,能够应用设计模式得心应手的解耦;在理论的简单业务中,当然也能够利用适合的设计模式。

这篇文章,我会将理论业务较为常见场景,如何适合将设计模式利用其中

  • 此处的利用绝不是生吞活剥,是我通过三思而行,并将较为简单的业务进行全面重构后,得出的一套卓有成效的思路历程
  • 任何一个设计模式都是一个平凡的教训及其思维总结,千人千面,如果对文章中内容,有不同的意见,心愿你能在评论中提出,咱们独特探讨,共同进步

本文章是一篇弱代码类型文章,我会画大量的图片向大家展现,援用设计模式后,会对原有的业务流程,产生什么样的影响。

前置常识

这里,须要理解下基础知识,什么是责任链模式和策略模式

责任链模式,在很多开源框架中都是有所利用,你如果听到啥啥拦截器,根本就是责任链模式,责任链模式的思维很简略,然而有很多种实现形式

  • 最简略的链表实现就和 OkHttp 的拦截器实现天壤之别
  • OkHttp 的拦截器实现和 Dio 拦截器实现构造雷同,但遍历形式不一样
  • 很多骚操作:我喜爱 OkHttp 的实现形式,喜爱 dio 的 Api 设计,结尾会给出一个联合这俩者思维的通用拦截器

策略模式,或是天生适宜业务,同一模块不同类型业务,如果行为雷同,或者就能够思考应用策略模式去解耦了

责任链模式

这边用 Dart 写一个简略的拦截器,dart 和 java 十分像

  • 为了缩小语言差别,我就不应用箭头语法了
  • 下划线示意公有

用啥语言不重要,这边只是用代码简略演示下思维

此处实现就用链表了;如果,应用数组的模式,须要多写很多逻辑,数组的优化写法在结尾给出,此处暂且不表

构造

  • 责任链的构造,通常有俩种构造

    • 链表构造:链表构建责任链,非常便捷的就能和下一节点建立联系
    • 数组构造:数组,用通用的 List 即可,不便增删,不固定长度(别吃力的用固定长度 Array 了,例如:int[]、String[])

  • 实现一个链表实体很简略
abstract class InterceptChain<T> {
  InterceptChain? next;

  void intercept(T data) {next?.intercept(data);
  }
}

实现

  • 拦截器实现
/// 该拦截器以最简略的链表实现
abstract class InterceptChain<T> {
  InterceptChain? next;

  void intercept(T data) {next?.intercept(data);
  }
}

class InterceptChainHandler<T> {
  InterceptChain? _interceptFirst;

  void add(InterceptChain interceptChain) {if (_interceptFirst == null) {
      _interceptFirst = interceptChain;
      return;
    }

    var node = _interceptFirst!;
    while (true) {if (node.next == null) {
        node.next = interceptChain;
        break;
      }
      node = node.next!;
    }
  }

  void intercept(T data) {_interceptFirst?.intercept(data);
  }
}
  • 应用

    • 调整 add 程序,就调整了对应逻辑的节点,在整个责任链中的程序
    • 去掉 intercept 重写办法中的 super.intercept(data),就能实现拦挡后续节点逻辑
void main() {var intercepts = InterceptChainHandler<String>();
  intercepts.add(OneIntercept());
  intercepts.add(TwoIntercept());
  intercepts.intercept("测试拦截器");
}

class OneIntercept extends InterceptChain<String> {
  @override
  void intercept(String data) {
    data = "$data:OneIntercept";
    print(data);
    super.intercept(data);
  }
}

class TwoIntercept extends InterceptChain<String> {
  @override
  void intercept(String data) {
    data = "$data:TwoIntercept";
    print(data);
    super.intercept(data);
  }
}
  • 打印后果
 测试拦截器:OneIntercept
测试拦截器:OneIntercept:TwoIntercept

策略模式

构造

  • 策略模式最重要的:应该就是对抽象类的设计,对行为的形象

实现

  • 定义抽象类,形象行为
/// 联合适配器模式的接口适配:形象必须实现行为,和可选实现行为
abstract class BusinessAction {
  /// 创立相应资源:该行为必须实现
  void create();

  /// 可选实现
  void dealIO() {}

  /// 可选实现
  void dealNet() {}

  /// 可选实现
  void dealSystem() {}

  /// 开释资源:该行为必须实现
  void dispose();}
  • 实现策略类
//Net 策略
class NetStrategy extends BusinessAction {
  @override
  void create() {print("创立 Net 资源");
  }

  @override
  void dealNet() {print("创立 IO 资源");
  }

  @override
  void dispose() {print("创立 Net 资源");
  }
}

///IO 策略
class IOStrategy extends BusinessAction {
  @override
  void create() {print("创立 IO 资源");
  }

  @override
  void dealIO() {print("解决 IO 逻辑");
  }

  @override
  void dispose() {print("开释 IO 资源");
  }
}
  • 应用
void main() {
  var type = 1;
  BusinessAction strategy;

  // 不同业务应用不同策略
  if (type == 0) {strategy = NetStrategy();
  } else {strategy = IOStrategy();
  }

  // 开始创立资源
  strategy.create();
  //......... 省略 N 多逻辑(其中某些场景,会有用到 Net 业务,和下面 type 是关联的)//IO 业务:开始解决业务
  strategy.dealIO();
  //......... 省略 N 多逻辑
  // 开释资源
  strategy.dispose();}
  • 后果
 创立 IO 资源
解决 IO 逻辑
开释 IO 资源 

适宜的业务场景

这边举一些适宜上述设计模式的业务场景,这些场景是实在存在的!

这些实在的业务,应用设计模式解耦和纯靠 if else 怼,齐全是俩种体验!

代码如诗,这并不是一句玩笑话。

连环弹窗业务

业务形容

连环弹窗夺命 call 来袭。。。

  • A 弹窗弹出:有确定和勾销按钮

    • 确定按钮:B 弹窗弹出(有查看详情和勾销按钮)

      • 查看详情按钮:C 弹窗弹出(有批准和回绝按钮)

        • 批准按钮:D 弹窗弹出(有查看和下一步按钮)

          • 查看按钮:E 弹窗弹出(只有下一步按钮)

            • 下一步按钮:F 弹窗弹出(完结)
          • 下一步按钮:F 弹窗弹出(完结)
        • 回绝按钮:流程完结
      • 勾销按钮:流程完结
    • 勾销按钮:流程完结

好家伙,套娃真是无所不在,真不是咱们代码套娃,切实是业务套娃,手动滑稽.jpng

  • 图示弹窗业务

间接开搞

看到这个业务,大家会去做呢?

  • 有人可能会想,这么简略的业务还须要想吗?间接写啊!

    • A:在确定回调外面,跳转 B 弹窗
    • B:查看详情按钮跳转 C 弹窗
    • 。。。
    • 好一通套后,终于写完了

产品来了,加需要

B 和 C 弹窗之间要加个预览 G 弹窗,点击 B 的查看详情按钮,跳转预览 G 弹窗,预览 G 弹窗只有一个确定按钮,跳转 C 弹窗

  • 你心里可能要想了,这特么不是坑爹?

    • 业务原本就超吉尔套,我 B 弹窗外面写的跳转代码要改,传参要改,而且还要加弹窗!
  • 先要找产品撕逼,撕结束后

    • 而后持续在屎山上,小心翼翼的再拉了坨 shit
    • 这座克苏鲁山初成规模

产品又来了,第一稿需要不合理,须要调整需要

替换 C 和 D 弹窗地位,D 弹窗点击下一步的时候,须要加一个校验申请,通过后能力跳转到 C 弹窗

  • 你眉头一皱,发现事件没有外表这么简略

    • 因为初期图简略,简直都写在一个文件里,目迷五色弹窗回调太多,而且弹窗款式也不一样
    • 当初改整个流程,导致你整个人脑子嗡嗡响
  • 心中喜气翻涌,找到产品说

  • 回来,坐在椅子上,心里想:

    • 老夫写的代码浑然一体,这什么几把需要
    • 可恶,这次测试,起码要给我多提十几个 BUG

  • 克苏鲁山开始狰狞

产品飘来,加改需要:如此,如此,,,这般,这般,,,

  • 你 ….

产品:改下,,,而后,扔给你几十页的 PRD

  • 你看了看这改了几十版的克苏鲁山,这几十个弹窗逻辑竟然都写在一个文件里,快一万行的代码。。。

    • 心里不禁想:本帅比写的代码果然牛批,或者这就是艺术!艺术总是曲高和寡,难被人了解!而我的代码更牛批,连我本人都看不懂了!

  • 心想:事了拂衣去,深藏功与名

重构

随着业务的逐步简单,最后的设计毛病会逐步裸露;重构有缺点的代码流程,变得势在必行,这会极大升高保护老本

如果心中对责任链模式有一些概念的话,会发现下面的业务,极其适宜责任链模式!

对下面的业务进行剖析,能够明确一些事

  • 这个业务是一个链式的,有着较明确方向性,单向,从头到尾指向
  • 业务拆离开,能够将一个弹窗作为颗粒度,一个弹窗作为节点
  • 下级的业务节点能够对上级节点拦挡(点击勾销,回绝按钮,不再进行后续业务)

重构下面的代码,只有明确思维和流程就行了

第一稿业务

  • 业务流程

  • 责任链

  • 代码:简写
void main() {var intercepts = InterceptChainHandler<String>();
  intercepts.add(AIntercept());
  intercepts.add(BIntercept());
  intercepts.add(CIntercept());
  intercepts.add(DIntercept());
  intercepts.add(EIntercept());
  intercepts.add(FIntercept());
  intercepts.intercept("测试拦截器");
}

第二稿业务

  • 业务流程

  • 责任链

  • 代码:简写
void main() {var intercepts = InterceptChainHandler<String>();
  intercepts.add(AIntercept());
  intercepts.add(BIntercept());
  intercepts.add(GIntercept());
  intercepts.add(CIntercept());
  intercepts.add(DIntercept());
  intercepts.add(EIntercept());
  intercepts.add(FIntercept());
  intercepts.intercept("测试拦截器");
}

第三稿业务

  • 业务流程

  • 责任链

  • 代码:简写
void main() {var intercepts = InterceptChainHandler<String>();
  intercepts.add(AIntercept());
  intercepts.add(BIntercept());
  intercepts.add(GIntercept());
  intercepts.add(DIntercept());
  intercepts.add(CIntercept());
  intercepts.add(EIntercept());
  intercepts.add(FIntercept());
  intercepts.intercept("测试拦截器");
}

总结

通过责任链模式重构后,业务节点被明确的辨别开,整个流程从代码上看,都相当的分明,保护将变的异样轻松;或者,此时能感触到一些,编程的乐趣了

花色弹窗业务

业务形容

这边来形容一个业务,这个业务场景实在存在某办公软件

  • 进入 APP 首页,而后和后盾建设一个长连贯
  • 后盾某些工单解决后,会告诉 APP 解决,此时 app 会弹出解决工单的弹窗(app 顶部)
  • 弹窗类型很多:工单解决弹窗,流程审批弹窗,邀请类型弹窗,查看工单详情弹窗,提交信息弹窗。。。
  • 弹窗弹出类型,是依据后盾给的 Type 进行判断:从而弹出不同类型弹窗、点击其按钮,跳转不同业务,传递不同参数。

剖析

确定设计

这个业务,是一种渐变性的疏导你搭建克苏鲁代码山

  • 在后期开发的时候,个别只有俩三种类型弹窗,后期非常好做;基本不必思考如何设计,抬手一行代码,反手一行代码,就能搞定
  • 然而起初整个业务会慢慢的鬼畜,不同类型会缓缓加到几十种之多!!!

首先这个业务,应用责任链模式,必定是不适合的,因为弹窗之间的耦合性很低,并没有什么明确的上下游关系

然而,这个业务应用策略模式十分的适宜!

  • type 类型明确:不同类型弹出不同弹窗,按钮执行不同逻辑
  • 形象行为明确:一个按钮就是一种行为,不同行为的实现逻辑天壤之别

形象行为

多样弹窗的行为形象,对应其按钮就行了

确定、勾销、批准、回绝、查看详情、我晓得了、提交

间接画图来示意吧

实现

来看下简要的代码实现,代码不重要,重要的是思维,这边简要的看下代码实现流程

  • 形象基类
/// 默认实现抛异样, 可揭示未实现办法被误用
abstract class DialogAction {
  /// 确定勾销
  void onConfirm() {throw 'DialogAction:not implement onConfirm()';
  }

  /// 勾销
  void onCancel() {throw 'DialogAction:not implement onCancel()';
  }

  /// 批准
  void onAgree() {throw 'DialogAction:not implement onAgree()';
  }

  /// 回绝
  void onRefuse() {throw 'DialogAction:not implement onRefuse()';
  }

  /// 查看详情
  void onDetail() {throw 'DialogAction:not implement onDetail()';
  }

  /// 我晓得了
  void onKnow() {throw 'DialogAction:not implement onKnow()';
  }

  /// 提交
  void onSubmit() {throw 'DialogAction:not implement onSubmit()';
  }
}
  • 实现逻辑类
class OneStrategy extends DialogAction {
  @override
  void onConfirm() {print("确定");
  }

  @override
  void onCancel() {print("勾销");
  }
}

class TwoStrategy extends DialogAction{
  @override
  void onAgree() {print("批准");
  }
  
  @override
  void onRefuse() {print("回绝");
  }
}

//........ 省略其余实现 
  • 应用
void main() {
  // 依据接口获取
  var type = 1;
  DialogAction strategy;
  switch (type) {
    case 0:
      strategy = DefaultStrategy();
      break;
    case 1:
      strategy = OneStrategy();
      break;
    case 2:
      strategy = TwoStrategy();
      break;
    case 3:
      strategy = ThreeStrategy();
      break;
    case 4:
      strategy = FourStrategy();
      break;
    case 5:
      strategy = FiveStrategy();
      break;
    default:
      strategy = DefaultStrategy();
      break;
  }

  // 聚合弹窗按钮触发事件
  BusinessDialog(
    // 确定按钮
    onConfirm: () {strategy.onConfirm();
    },
    // 勾销按钮
    onCancel: () {strategy.onCancel();
    },
    // 批准按钮
    onAgree: () {strategy.onAgree();
    },
    // 回绝按钮
    onRefuse: () {strategy.onRefuse();
    },
    // 查看详情按钮
    onDetail: () {strategy.onDetail();
    },
    // 我晓得了按钮
    onKnow: () {strategy.onKnow();
    },
    // 提交按钮
    onSubmit: () {strategy.onSubmit();
    },
  );
}
  • 图示

一个简单业务场景的演变

咱们看下,一个简略的提交业务流,怎么逐步变的狰狞

我会逐步给出一个适合的解决方案,如果大家有更好的想法,务必在评论区通知鄙人

业务形容:咱们的车子因不可抗起因坏了,要去维修厂修车,工作人员开始注销这个损坏车辆。。。

业务的演变

第一稿

初始业务

注销一个培修车辆的流程,实际上还是满麻烦的

  • 注销一个新车,须要将车辆详细信息注销分明:车牌、车架、车型号、车辆类型、进出场工夫、油量、里程。。。
  • 还须要注销一下用户信息:姓名、手机号、是否附属公司。。。
  • 注销车损水平:车顶、车底、方向盘、玻璃、离合器、刹车。。。
  • 车内物品:车座皮套、工具。。。
  • 以及其余我没想到。。。
  • 最初:提交所有注销好的信息

第一稿,业务流程非常清晰,细节简单,然而做起来不难

第二稿(理论是多稿聚合):减少下述几个流程

内部注销:内部注销了一个培修车辆局部信息(后盾,微信小程序,H5 等等),须要在 app 上欠缺信息,提交接口不同(必带车牌号)

快捷洗车:洗车业务极其常见,快捷生成对应信息,提交接口不同

预约订单注销:预约好了车辆一部分一些信息,可快捷注销,提交接口不同(必带车牌号)

因为注销培修车辆流程,注销车辆信息流程极其粗疏繁琐,咱们决定复用注销新车模块

  • 因为此处逻辑大多波及结尾和结尾,两头注销车辆信息操作简直未改变,复用想法是可行的
  • 如果减少车辆注销项,新的三个流程必须也须要提交这些信息,复用势在必行

因为这一稿需要,业务也变得更加简单

第三稿

当初要针对不同的车辆类型,做不同的解决;车类型分:集体车,团体车

不同类型的注销,在提交的时候,须要校验不同的信息;校验不通过,须要提醒用户,并且不能进行提交流程

提交完,解决下通用也通用业务,而后跳转的某个页面

第三稿的形容不多,然而,也同样大大的减少了复杂度

  • 尤其是不同类型校验过程还不同,还能中断后续提交流程
  • 提交流程后,还须要跳转通用页面

开发探讨

第一稿

  • 业务流程

  • 开发

失常流程开发、、、

第二稿

  • 业务流程

  • 思考

对于第二稿的业务,能够好好的思考,能够怎么去开发?

结尾和结尾须要独自写判断,去解决不同流程的业务,这至多要写俩个大的判断模块,承受数据的入口模块可能还要写判断

这样就非常适合策略模式去做了

结尾依据执行的流程,抉择相应的策略对象,后续将逻辑块替换形象的策略办法就 OK 了,大抵流程如下

第三稿

业务流程

探讨

  • 第三稿的需要,实际上,曾经比较复杂了

    • 整个流程中掺杂着不同业务流程解决,不同流程逻辑又领有阻断上游机制(绿色模块)
    • 上游逻辑又会合流(结尾)的多种变换
  • 在这一稿的需要

    • 应用策略模式必定是能够的
    • 阻断那块(绿色模块)须要独自解决下: 形象办法应该领有返回值,外层依据返回值,判断是否进行后续流程
    • 但!这!也太不优雅了!
  • 思考下面业务一些个性

    • 拦挡上游机制
    • 上游到上游、方向明确
    • 随时可能插入新的业务流程。。。

能够用责任链模式!须要做一些小改变!这中央,咱们须要将频繁变动的模块用责任链模式全都隔离进去

  • 看下,应用责任链模式革新后流程图

浏览上述流程图可发现,原本是极度芜杂糅合的业务,能够被设计绝对更加平行的构造

  • 对于上述流程,能够进一步剖析,并进一步简化:对整体业务剖析,咱们须要去关注其变或不变的局部

    • 不变:整体业务变动很小的是,注销信息流程(主题逻辑这块),此处的相干变动是很小的,对所有流程也是共用的局部
    • 变:能够发现,结尾和结尾是变动更加频繁的局部,咱们能够对此处逻辑进行整体的形象
  • 形象多变的结尾和结尾

  • 所以咱们形象拦挡类,能够做一些调整
abstract class InterceptChainTwice<T> {
  InterceptChainTwice? next;

  void onInit(T data) {next?.onInit(data);
  }

  void onSubmit(T data) {next?.onSubmit(data);
  }
}

来看下简要的代码实现,代码不重要,次要看看实现流程和思维

  • 形象拦截器
abstract class InterceptChainTwice<T> {
  InterceptChainTwice? next;

  void onInit(T data) {next?.onInit(data);
  }

  void onSubmit(T data) {next?.onSubmit(data);
  }
}

class InterceptChainTwiceHandler<T> {
  InterceptChainTwice? _interceptFirst;

  void add(InterceptChainTwice interceptChain) {if (_interceptFirst == null) {
      _interceptFirst = interceptChain;
      return;
    }

    var node = _interceptFirst!;
    while (true) {if (node.next == null) {
        node.next = interceptChain;
        break;
      }
      node = node.next!;
    }
  }

  void onInit(T data) {_interceptFirst?.onInit(data);
  }

  void onSubmit(T data) {_interceptFirst?.onSubmit(data);
  }
}
  • 实现拦截器
/// 结尾通用拦截器
class CommonIntercept extends InterceptChainTwice<String> {
  @override
  void onInit(String data) {
    // 如果有车牌,申请接口,获取数据
    //.................
    // 填充页面
    super.onInit(data);
  }
}

/// 注销新车拦截器
class RegisterNewIntercept extends InterceptChainTwice<String> {
  @override
  void onInit(String data) {
    // 解决结尾针对注销新车的独自逻辑
    super.onInit(data);
  }

  @override
  void onSubmit(String data) {
    var isPass = false;
    // 如果校验不过,拦挡上游逻辑
    if (!isPass) {return;}
    // ......
    super.onSubmit(data);
  }
}

/// 省略其余实现 
  • 应用
void main() {
  var type = 0;
  var intercepts = InterceptChainTwiceHandler();

  intercepts.add(CommonIntercept());
  intercepts.add(CarTypeDealIntercept());
  if (type == 0) {
    // 注销新车
    intercepts.add(CommonIntercept());
  } else if (type == 1) {
    // 内部注销
    intercepts.add(OutRegisterIntercept());
  } else if (type == 2) {
    // 快捷洗车
    intercepts.add(FastWashIntercept());
  } else {
    // 预约订单注销
    intercepts.add(OrderRegisterIntercept());
  }
  intercepts.add(TailIntercept());

  // 业务开始
  intercepts.onInit("传入数据源");

  // 开始解决 N 多逻辑
  //............................................................
  // 经验了 N 多逻辑

  // 提交按钮触发事件
  SubmitBtn(
    // 提交按钮
    onSubmit: () {intercepts.onSubmit("传入提交数据");
    },
  );
}

总结

对于代码局部,要害的代码,我都写进去,用心看看,必定能明确我写的意思

也不必找我要残缺代码了,这些业务 demo 代码写完后,就删了

本栏目这个业务,实际上是十分常见的的一个业务,一个提交流程与很多其它的流程耦合,整个业务就会缓缓的变的鬼畜,充斥各种判断,很容易让人陷入泥泞,或者,此时能够对已有业务进行思考,如何进行正当的优化

该业务的演变历程,和开发革新是自己的一次思路历程,如大家有更好的思路,还请不吝赐教。

通用拦截器

我联合 OkHttp 的思维和 Dio 的 API,封装了俩个通用拦截器,这边贴下代码,如果哪里有什么有余,请及时告知自己

阐明下:这是 Dart 版本的

形象单办法

/// 一层通用拦截器,T 的类型必须统一
abstract class InterceptSingle<T> {void intercept(T data, SingleHandler handler) => handler.next(data);
}

/// 增加拦截器, 触发拦截器办法入口
class InterceptSingleHandler<T> {
  _InterceptSingleHandler _handler = _InterceptSingleHandler(
    index: 0,
    intercepts: [],);

  void add(InterceptSingle intercept) {
    // 一种类型的拦截器只能增加一次
    for (var item in _handler.intercepts) {if (item.runtimeType == intercept.runtimeType) {return;}
    }

    _handler.intercepts.add(intercept);
  }

  void delete(InterceptSingle intercept) {_handler.intercepts.remove(intercept);
  }

  void intercept(T data) {_handler.next(data);
  }
}

///------------ 实现不同处理器 参照 dio api 设计 和 OkHttp 实现思维 ---------------
abstract class SingleHandler {next(dynamic data);
}

/// 实现 init 处理器
class _InterceptSingleHandler extends SingleHandler {
  List<InterceptSingle> intercepts;

  int index;

  _InterceptSingleHandler({
    required this.index,
    required this.intercepts,
  });

  @override
  next(dynamic data) {if (index >= intercepts.length) {return;}

    var intercept = intercepts[index];
    var handler =
        _InterceptSingleHandler(index: index + 1, intercepts: intercepts);

    intercept.intercept(data, handler);
  }
}

形象单方法

/// 俩层通用拦截器,T 的类型必须统一
abstract class InterceptTwice<T> {void onInit(T data, TwiceHandler handler) => handler.next(data);

  void onSubmit(T data, TwiceHandler handler) => handler.next(data);
}

/// 增加拦截器, 触发拦截器办法入口
class InterceptTwiceHandler<T> {_TwiceInitHandler _init = _TwiceInitHandler(index: 0, intercepts: []);
  _TwiceSubmitHandler _submit = _TwiceSubmitHandler(index: 0, intercepts: []);

  void add(InterceptTwice intercept) {
    // 一种类型的拦截器只能增加一次
    for (var item in _init.intercepts) {if (item.runtimeType == intercept.runtimeType) {return;}
    }

    _init.intercepts.add(intercept);
    _submit.intercepts.add(intercept);
  }

  void delete(InterceptTwice intercept) {_init.intercepts.remove(intercept);
    _submit.intercepts.remove(intercept);
  }

  void onInit(T data) {_init.next(data);
  }

  void onSubmit(T data) {_submit.next(data);
  }
}

///------------ 实现不同处理器 参照 dio api 设计 和 OkHttp 实现思维 ---------------
abstract class TwiceHandler {next(dynamic data);
}

/// 实现 init 处理器
class _TwiceInitHandler extends TwiceHandler {
  List<InterceptTwice> intercepts;

  int index;

  _TwiceInitHandler({
    required this.index,
    required this.intercepts,
  });

  @override
  next(dynamic data) {if (index >= intercepts.length) {return;}

    var intercept = intercepts[index];
    var handler = _TwiceInitHandler(index: index + 1, intercepts: intercepts);

    intercept.onInit(data, handler);
  }
}

/// 实现 submit 处理器
class _TwiceSubmitHandler extends TwiceHandler {
  List<InterceptTwice> intercepts;

  int index;

  _TwiceSubmitHandler({
    required this.index,
    required this.intercepts,
  });

  @override
  next(dynamic data) {if (index >= intercepts.length) {return;}

    var intercept = intercepts[index];
    var handler = _TwiceSubmitHandler(index: index + 1, intercepts: intercepts);

    intercept.onSubmit(data, handler);
  }
}

最初

第一次,写这种联合业务的文章

如有播种,还请点个赞,让我感触到你读有所获~~~~

感激浏览,下次再会~~

正文完
 0