登录  /  注册
博主信息
博文 64
粉丝 2
评论 3
访问量 73928
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
Thinkphp5.1 容器于门面的认识—2018年5月29日08:51:45
清雨的博客
原创
1355人浏览过

在官方文档中对容器(Container):用来更方便的管理类依赖及运行依赖注入。

门面(Facade):门面为容器中的类提供了一个静态调用接口,相比于传统的静态方法调用, 带来了更好的可测试性和扩展性,你可以为任何的非静态类库定义一个facade类。


容器主要是由think\Container 类完成,单大多数情况是由助手函数完成操作。

看源代码的实现方式

实例

// 注册核心类的静态代理
Facade::bind([
    facade\App::class        => App::class,
    facade\Build::class      => Build::class,
    facade\Cache::class      => Cache::class,
    facade\Config::class     => Config::class,
    facade\Cookie::class     => Cookie::class,
    facade\Debug::class      => Debug::class,
    facade\Env::class        => Env::class,
    facade\Hook::class       => Hook::class,
    facade\Lang::class       => Lang::class,
    facade\Log::class        => Log::class,
    facade\Middleware::class => Middleware::class,
    facade\Request::class    => Request::class,
    facade\Response::class   => Response::class,
    facade\Route::class      => Route::class,
    facade\Session::class    => Session::class,
    facade\Url::class        => Url::class,
    facade\Validate::class   => Validate::class,
    facade\View::class       => View::class,
]);

// 注册类库别名
Loader::addClassAlias([
    'App'      => facade\App::class,
    'Build'    => facade\Build::class,
    'Cache'    => facade\Cache::class,
    'Config'   => facade\Config::class,
    'Cookie'   => facade\Cookie::class,
    'Db'       => Db::class,
    'Debug'    => facade\Debug::class,
    'Env'      => facade\Env::class,
    'Facade'   => Facade::class,
    'Hook'     => facade\Hook::class,
    'Lang'     => facade\Lang::class,
    'Log'      => facade\Log::class,
    'Request'  => facade\Request::class,
    'Response' => facade\Response::class,
    'Route'    => facade\Route::class,
    'Session'  => facade\Session::class,
    'Url'      => facade\Url::class,
    'Validate' => facade\Validate::class,
    'View'     => facade\View::class,
]);

运行实例 »

点击 "运行实例" 按钮查看在线实例

容器的实现方式:

在这里容器已经绑定了系统常用的类到了容器中,在使用时只需要调用助手函数app()进行容器猴子那个的类解析调用方可,对于已经绑定的的类,会自动进行实例化。

实例

//查看源码,Container调用的其实是make方法,在该方法里调用反射等实现类的实例化,过程如下:
 /**
     * 创建类的实例
     * @access public
     * @param  string        $abstract       类名或者标识
     * @param  array|true    $vars           变量
     * @param  bool          $newInstance    是否每次创建新的实例
     * @return object
     */
    public function make($abstract, $vars = [], $newInstance = false)
    {
        if (true === $vars) {
            // 总是创建新的实例化对象
            $newInstance = true;
            $vars        = [];
        }

        $abstract = isset($this->name[$abstract]) ? $this->name[$abstract] : $abstract;

        if (isset($this->instances[$abstract]) && !$newInstance) {
            return $this->instances[$abstract];
        }

        if (isset($this->bind[$abstract])) {
            $concrete = $this->bind[$abstract];
             //闭包实现
            if ($concrete instanceof Closure) {
                $object = $this->invokeFunction($concrete, $vars);
            } else {
                $this->name[$abstract] = $concrete;
                return $this->make($concrete, $vars, $newInstance);
            }
        } else {
           //反射实现
            $object = $this->invokeClass($abstract, $vars);
        }

        if (!$newInstance) {
            $this->instances[$abstract] = $object;
        }

        return $object;
    }



 /**
     * 调用反射执行类的实例化 支持依赖注入
     * @access public
     * @param  string    $class 类名
     * @param  array     $vars  参数
     * @return mixed
     */
    public function invokeClass($class, $vars = [])
    {
        try {
            $reflect = new ReflectionClass($class);

            if ($reflect->hasMethod('__make')) {
                $method = new ReflectionMethod($class, '__make');

                if ($method->isPublic() && $method->isStatic()) {
                    $args = $this->bindParams($method, $vars);
                    return $method->invokeArgs(null, $args);
                }
            }

            $constructor = $reflect->getConstructor();

            $args = $constructor ? $this->bindParams($constructor, $vars) : [];

            return $reflect->newInstanceArgs($args);

        } catch (ReflectionException $e) {
            throw new ClassNotFoundException('class not exists: ' . $class, $class);
        }
    }





    /**
     * 执行函数或者闭包方法 支持参数调用
     * @access public
     * @param  mixed  $function 函数或者闭包
     * @param  array  $vars     参数
     * @return mixed
     */
    public function invokeFunction($function, $vars = [])
    {
        try {
            $reflect = new ReflectionFunction($function);

            $args = $this->bindParams($reflect, $vars);

            return call_user_func_array($function, $args);
        } catch (ReflectionException $e) {
            throw new Exception('function not exists: ' . $function . '()');
        }
    }

运行实例 »

点击 "运行实例" 按钮查看在线实例

用简单点的来说就是,容器内部是通过反射类或者是闭包函数的方式来实现实例化。

门面实现


批改状态:未批改

老师批语:
本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
1条评论
天蓬老师 2018-05-30 09:22:53
仅将官方文档中的内容简单的复制粘贴,而无自己的独立见解,难以领会外观模式Facade的精华~~ 二点建议: 1. 不要抄官方源码,自己写源码进行描述; 2. 加上自己对该设计模式的理解,哪怕是有偏差的也没关系; 希望你重新完成本次作业~~
1楼
作者最新博文
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学