如何灵活配置多版本业务流程?

说明#

我先举个例子:我从家起床到学校去上课,这期间我需要做这些事情:洗漱吃饭收拾书包交通。这些事情可以做很多种排序,简单举两个:

  • 顺序 1:洗漱吃饭收拾书包交通#
  • 顺序 2:收拾书包吃饭洗漱交通#
  • 顺序 3:吃饭洗漱收拾书包交通#

如果我是一个做事很讲规矩的人,那么,我每天都会按照顺序1 来做。
可是巧了,我是一个很随性的人,我偏要一三五按照顺序2 做,二四六按照顺序3 做,周日啥都不不做(躺一天)。

问题#

对应到业务代码中,我们怎么去灵活的定义多个版本的业务流程呢?

砖头#

我先抛个砖,希望大佬能有更好的实现方式。
首先,在 controller 中,定义出洗漱吃饭收拾书包交通等方法。

class Controller
{
    public function wash(){
        // 假装有业务代码
    }
    public function eat(){}
    public function packUp(){}
    public function traffic(String $kind){}
}

然后再定义一个流程变量,将顺序1 放入其中:

class Controller
{
    public $assembly_line_one = [
        [
            'info' => '洗漱',
            'func' => 'wash',
            'params' => [],
        ],
        [
            'info' => '吃饭',
            'func' => 'eat',
            'params' => [],
        ],
        [
            'info' => '收拾书包',
            'func' => 'packUp',
            'params' => [],
        ],
        [
            'info' => '交通',
            'func' => 'traffic',
            'params' => ['公交'],
        ],
    ];
    public function wash(){
        // 假装有业务代码
    }
    public function eat(){}
    public function packUp(){}
    public function traffic(String $kind){}
}

此时,我是一个老实人,只会按照这一个流程执行:

class Controller
{
    ...
    public function run()
    {
        // 按照 $assembly_line_one 定义的流程顺序执行
        foreach ($this->assembly_line_one as $step) {
            $this->{$step['func']}(...$step['params']);
        }
    }
}

那如果我是一个精分呢?就可以再多定义几个 $assembly_line_two$assembly_line_three 等等。

class Controller
{
    ...
    public function run()
    {
        $today_assembly_line = [];
        if($today->isMonday()){
            // 周一的顺序
            $today_assembly_line = $this->assembly_line_one;
        }
        if($today->isTuesday()){
            // 周二的顺序
            $today_assembly_line = $this->assembly_line_two;
        }
        foreach ($today_assembly_line as $step) {
            $this->{$step['func']}(...$step['params']);
        }
    }
}

以上的方式还可以进行下修改升级,将 func 的值设置为类似 SomeClass@func 的形式,这样就可以指定其他类中的方法去执行(当然 foreach 中的代码也需要同步修改做支持)。

最后#

以上仅是自己抖了个小机灵,有错误的地方还望指正。更希望各路大佬提供些更好的思路和现成的实现,我也学习一下。

再见了妈妈今晚我就要远航,别为我担心我有快乐和智慧的桨~
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 7
ShiKi

东西不入库吗?

3年前 评论
LiamHao (楼主) 3年前

考虑一些复杂的情况,你这种设计方案可能就不能很好处理了,比如,小明在天气晴的时候出行喜欢坐公交,天气阴的时候喜欢大车,而小刚则是雷打不动每天骑自行车。可以考虑自己实现一个精简的工作流引擎,其实你本身的方案就已经是一个最简的工作流的思想了。

3年前 评论
LiamHao (楼主) 3年前
liaosp 3年前

责任链模式申请出战

3年前 评论
zhangrongwang (作者) 3年前
LiamHao (楼主) 3年前
LiamHao (楼主) 3年前

策略总是需要人来做出选择的。除非用机器学习。

3年前 评论
  • 顺序 1:洗漱、吃饭、收拾书包、交通
  • 顺序 2:收拾书包、吃饭、洗漱、交通
  • 顺序 3:吃饭、洗漱、收拾书包、交通

抽象化设定

  1. 洗漱、吃饭、收拾书包、交通 每个都设定为 command
  2. 设定为 subject, 包含交通方式: 公交、骑马
  3. 设定流程为 handler 包含顺序 1 或顺序 2 或顺序 3

流程

  1. 定义 subject
  2. subject 传递给 handler
  3. handler 依次执行 command
  4. 每一个 command 都接收同一个 subject
  5. 最后结果返回给 handler

希望各路大佬提供些更好的思路和现成的实现,我也学习一下。

3年前 评论

symfony/workflow 可以满足上述需求。对应 Laravel 版本的 composer 包实现 adalessa/laravel-workflow 。感兴趣的话可以研究一下。

3年前 评论
悠悠山雨 3年前
LiamHao (楼主) 3年前