分类
php

门面模式是怎么回事

在 PHP 的各类框架中,Facade 模式使用得非常广泛。所以,这篇文档我们就来为我们自己的类库添加 Facade 模式。

什么是 Facade 模式

门面模式为 容器中的类提供了一个静态调用接口的方式。相比于传统的静态方法调用,带来了更好的可测试性以及可扩展性。

Request 类添加 Facade 类

在前面的文档中,我们已经实现了 Request 类,现在我们为这个类添加一个门面模式的类,使得我们可以使用调用静态方法的方式来调用 Request 中的实例方法。首先,我们先来回顾一下 Request 类:
PHP复制代码

<?php

class Request
{
  // 根据传入的 key 获取用户的请求参数
  public function input(?string $key = null) {}
}

然后我们来实现门面类:
PHP复制代码

<?php

use EShop\Request as ESShopRequest;

class Request extends Facade
{


    /**
     * 获取当前 Facade 对应类名
     * @access protected
     * @return string
     */
    protected static function getFacadeClass(): string
    {
        return ESShopRequest::class;      // 返回实际的 Reqeust 类
    }
}

从上面的代码我们可以看出,门面类只是一个代理的类,并没有完成任何实际的功能,只是我们通过门面类类操作实际的 Request 类而已。另外,我们发现,门面类 Request 继承了一个名为 Facade 的父类。这个父类怎么写的呢?
PHP复制代码

<?php
class Facade
{

    /**
     * 获取门面类
     * @return string
     */
    protected static function getFacadeClass(): string
    {
        return '';
    }

    /**
     * 创建门面类实例
     */
    protected static function createFacade()
    {
        // 通过静态延迟绑定来调用子类中的 getFacadeClass 方法,获取实际的类的类名
        $className = static::getFacadeClass();

        return (new $className);
    }

    /**
     * 调用实际的类
     * @param string $name
     * @param array $arguments
     * @return false|mixed
     */
    public static function __callStatic(string $name, array $arguments)
    {
        return call_user_func([self::createFacade(), $name], ...$arguments);
    }
}

这里面的关键就在于 __callStatic 这个魔术方法,它的作用是当静态调用了当前类中不存在的静态方法,则会执行。也就是说,当我们调用门面类的静态方法的时候,会执行这个 __callStatic 魔术方法,进而去调用实际的 Request 中的实际的方法。

接下来我们就可以通过如下方式来调用 Request 类中的 input 方法了:
PHP复制代码

<?php

var_dump(\EShop\Facade\Request::input());   // 通过静态方法的调用方式调用实际的实例方法

总结

我们看到,实际上门面模式只是一种让实例方法可以像静态方法一样去调用。而所谓的门面类只是实际类的一个代理类,通过 __callStatic 魔术方法来代理,这种个代理的设计模式在 PHP 的框架中非常之常见。除了使用 __callStatic 来代理外,我们也经常使用 __call 方法来代理某个类。

发表评论

邮箱地址不会被公开。 必填项已用*标注