回调 匿名函数和闭包

回调 匿名函数和闭包

<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/3
 * Time: 4:46 下午
 */

class mysql{
    public static function getlist($demo)
    {
        echo $demo;
    }
}



//回调静态方法
call_user_func(['mysql','getlist'],'params');
echo "<br/>";
$cal = new mysql();
//回掉普通方法
call_user_func([$cal,"getlist"],"class");
echo "<br/>";
function test($a,$b)
{
    echo "love"."----".$a."----".$b."<br>";
}

//回调方法
call_user_func('test','star','shine');

回调有什么用呢?它允许程序在运行期间将与组件核心任务没有直接关系的功能“插入“组件。通过让组件拥有回调能力,可以赋予其他程序员在我们不知道的上下文中扩展代码的能力。

假设ProcessSale类的客户端程序员希望创建一条销售记录。如果改程序员可以修改这个类,这一版是不可行的。就算他是包的维护者,在sale()方法中加入许多附带功能也会干扰它的核心职责。

所以我们可以让ProcessSale创建一个回掉的功能。然后将我们自己需要的逻辑放入外面的方法,通过回掉的方式机进行访问。

<?php
/**
 * 创建普通的匿名函数
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/3
 * Time: 3:11 下午
 */
class product{
    public $name;
    public $price;

    public function __construct(string $name,float $price)
    {
        $this->name = $name;
        $this->price = $price;
    }

}

class ProcessSale{
    private $callbacks;

    public function registerCallback(callable $callback)
    {
        if(! is_callable($callback)){
            throw new Exception("callable not callable");
        }
        $this->callbacks[] = $callback;
    }

    public function sale(product $product){
        print "{$product->name}:processing \n";
        foreach ($this->callbacks as $callback){
            call_user_func($callback,$product);
        }
    }

}
//create_function 创建匿名函数,回调的时候使用
$logger = create_function(
     '$project',
     'print "logging({$project->name})\n";'
);
/**
 * 执行流程
 * 实例化一个销售处理类,用注册回掉registerCallback的方法接收回调函数
 * 使用sale方法接收product实例化的类,此类自动调用输出名字$name
 * call_user_func函数使用匿名中的函数,输入name
 */
$processor = new ProcessSale();
$processor->registerCallback($logger);

$processor->sale(new product("shoes",6));
echo "<br/>";
// $processor->sale(new product("coffee",6));


较为简洁的回调方式

新语法创建一个Mailer类,其中只有一个方法doMail,这个方法用于接收$product对象作为参数并且输出关于一天他的消息。
在调用registerCallback时传入类一个数组作为参数,这个数组第一个元素是Mailer对象,第二个元素是要调用的方法的名字的字符串。

include "base.php";

/**
 * Class Mailer
 */
class Mailer{
    public function doMail(product $product)
    {
        print "mailing ({$product->name})\n";//输出销售记录,编写这个类,就可以在让访问ProcessSale类的时候,进行一个和上下代码不相关的逻辑。
    }
}

$processor = new ProcessSale();
$processor->registerCallback([new Mailer(),"doMail"]);//回调函数
print "\n";
$processor->sale(new product("coffee",6));

余下还有,需要再补

posted on 2020-08-06 17:51  誓_言  阅读(107)  评论(0)    收藏  举报

导航