以级联方式运行类方法


Running class methods in cascade

我有一个系统,它被设计成一种级联——在前一个条件成功时获得调用的方法序列。

示例是下面的代码,我认为这不是这样做的最佳实践,所以如果我能得到一些重构它的建议,可能使用设计模式或不同于这个系统,那就太好了。

<?php
class Model
{
    public function isOk()
    {
        return true;
    }
}
class OtherClass
{
    public function isOk()
    {
        return true;
    }
}
class AnotherClass
{
    public function verifies()
    {
        return true;
    }
}
class Sequence
{
    public function fire()
    {
        $model = new Model();
        if($model->isOk()) {
            $otherclass = new OtherClass();
            if($otherclass->isOk()) {
                $anotherclass = new AnotherClass();
                if($anotherclass->verifies()) {
                    echo "We're done with the sequence.";
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}
$sequence = new Sequence();
echo $sequence->fire();
?>

为了提高可读性,我会避免if/else语句的深度嵌套。一种方法是使用early return:

class Test1
{
    public function isOk()
    {
        echo 'Test1';
        return true;
    }
}
class Test2
{
    public function isOk()
    {
        echo 'Test2';
        return true;
    }
}
class Sequence
{
    public function fire()
    {
        $test1 = new Test1();
        if (!$test1->isOk()) {
            return false;
        }
        $test2 = new Test2();
        if (!$test2->isOk()) {
            return false;
        }
        echo "We're done with the sequence.";
        return true;
    }
}

如果你需要更动态地使用call_user_func或call_user_func_array。

class Sequence
{
    protected $sequence = array(
        array('Test1', 'isOk'),
        array('Test2', 'isOk'),
    );
    public function fire()
    {
        foreach ($this->sequence as $callback) {
            if (!call_user_func(array(new $callback[0], $callback[1]))) {
                return false;
            }
        }
        echo "We're done with the sequence.";
        return true;
    }
}