本文来自pilishen.com----原文链接; 欢迎作客我们的php&Laravel学习群:109256050

该篇翻译整理自laravel创始人Taylor的文章:Expressive Code & Real Time Facades,属于《Laravel底层核心技术实战揭秘》这一课程《laravel底层核心概念解析》这一章的扩展阅读。

laravel 5.4引入了realtime facade的功能,也即任何一个class都可以随时拿来当facade用,只要在其namespace前面加上Facades前缀即可。当然这个功能不可能随处都用到,但是偶尔呢,用它可以实现更简洁优雅、易于测试的代码方案。虽然下面的例子讲的是laravel 5.4的realtime facade,但是呢,其实也完全可以用在之前的版本上,因为所谓的realtime facade,无非就是系统自动给你注册成facade而已,鉴于这个功能又不可能到处用到,所以即使在老的版本里,如果你发现facade的这种代码实现方式更有吸引力,那么自己手动注册一个facade也完全可以的。

接下来的示例是关于Laravel Forge的,laravel Forge是laravel官方推出的laravel项目部署管理平台。当使用Forge的时候,你得在Forge后台将你服务器提供商的账号信息填上,然后呢交由Forge来具体管理。那么,这里假设呢我们有一个Model叫Provider,也就是对应着不同的主机提供商,比如国外的DigitalOcean、国内的阿里云等。

<?php
use App;
use Illuminate\Database\Eloquent\Model;
class Provider extends Model
{//
}

这里呢假设我们将所有处理外来API请求的class放在App\Services文件夹下,我们得对应每一个主机供应商都有一个“service”class,假设DigitalOcean这家供应商的service class是这样的:

<?php
namespace App\Services;
use App\Contracts\ServerProvider;
class DigitalOcean implements ServerProvider
{public function createServer($name, $size){//}
}

接下来呢,我们得能够解析这个服务类,基于我们model里的type这一栏的信息,我们可以使用工厂(factory)模式来实现:

<?php
namespace App\Services;
use InvalidArgumentException;class ServerProviderFactory
{public function make($type){switch ($type) {case 'DigitalOcean':return new DigitalOcean;case 'Linode':return new Linode;default:throw new InvalidArgumentException;}}
}

然后呢,我们就可以在需要的地方调用这个工厂,来相应地创建一个server 服务,比如假设在controller里调用:

<?php
namespace App\Http\Controllers;
use App\Provider;
use Illuminate\Http\Request;
use App\Services\ServerProviderFactory;class ServerController extends Controller
{protected $factory;public function __construct(ServerProviderFactory $factory){$this->factory = $factory;}public function store(Request $request, Provider $provider){$service = $this->factory->make($provider->type);$response = $service->createServer($request->name, $request->size);//}
}

但是呢,我觉得这样还是有些繁琐,我想要是这样来用该多好呢?

<?php
namespace App\Http\Controllers;
use App\Provider;
use Illuminate\Http\Request;
class ServerController extends Controller
{public function store(Request $request, Provider $provider){$repsonse = $provider->service()->createServer($request->name, $request->size);//}
}

我们只想简单地调用Provider这个实例上的service方法,然后就能获取到其背后对应的供应商,然后就能直接地createServer。这样来写呢,可能更像是我们日常中最直接的思考过程,虽然可能背后具体怎么实现你还没搞懂。那么怎么来实现呢?假设不借助facade,我们或许可以这样:

<?php
namespace App;
use App\Services\ServerProviderFactory;
use Illuminate\Database\Eloquent\Model;class Provider extends Model
{public function service(){return (new ServerProviderFactory)->make($this->type);}
}

貌似可行。但是这样呢,因为这个factory类是直接在service方法内部实例化的,这是不好的,后期我们无法用它来mock测试。那么如果用realtime facade的方式会怎么样呢?

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Facades\App\Services\ServerProviderFactory;class Provider extends Model
{public function service(){return ServerProviderFactory::make($this->type);}
}

现在,不仅看起来更简洁优雅,而且也可以测试了,因为facade可以进行mock,比如说这样:

<?php
namespace Tests\Feature;
use Mockery;
use App\Provider;
use Tests\TestCase;
use App\Contracts\ServerProvider;
use Facades\App\Services\ServerProviderFactory;
use Illuminate\Foundation\Testing\RefreshDatabase;class ExampleTest extends TestCase
{public function testBasicTest(){$provider = factory(Provider::class)->create(['id' => 1,'type' => 'DigitalOcean',]);$service = Mockery::mock(ServerProvider::class);ServerProviderFactory::shouldReceive('make')->with('DigitalOcean')->andReturn($service);$service->shouldReceive('createServer')->once()->with('web', '2GB')->andReturn('server-id');$response = $this->json('POST', '/api/providers/1/server', ['name' => 'web','size' => '2GB',]);$response->assertStatus(201);}
}

你会发现real-time facade最有用的地方就是构建简洁、优雅的object APIs,同时呢又不会影响到代码的可测试性。希望这能给你的实际开发带来一定启发。

通过facade(尤其是realtime facade)来使代码更优雅相关推荐

  1. 重构-使代码更简洁优美:实际经验之谈(提供一技巧,让你省掉N多代码)

    这几天没怎么写文,因为在用 CYQ.Data  框架 重构以前的一个博客源码,而在重构的过程中,最关键的就是简化代码了. 今天,我将说一个很典型的示例,看完本示例后,不要惊讶,不要怀疑,它不是神马,也 ...

  2. 3 个可以使你的 Python 代码更优雅、可读、直观和易于维护的工具

    Python 提供了一组独特的工具和语言特性来使你的代码更加优雅.可读和直观. 为正确的问题选择合适的工具,你的代码将更易于维护. 粉丝福利!私信回复[01]有基础教程一套 魔术方法 让我们创建一个 ...

  3. android 揭示动画_如何使用意图揭示函数名称使代码更好

    android 揭示动画 Discover Functional JavaScript was named one of the best new Functional Programming boo ...

  4. perl调用其他的perl_如何使Perl更优雅

    perl调用其他的perl 这是关于将代码从Perl 5迁移到Perl 6 的系列文章中的第七篇 .本文着眼于如何在Perl 6中创建类(对象)以及它与Perl 5的区别. Perl 5具有非常基本的 ...

  5. 三插头内部结构图_三方面维护硬度计才能使寿命更长久

    硬度计是光机电一体化的高新技术产品.与其他精密仪器一样,定期的保养维护少不了.轻则导致操作不顺畅,或试验结果有偏差;重则机器损坏,返厂维修耽误时间又费钱.如何才能使用寿命才能更长?现在为大家介绍一下在 ...

  6. 自定义linux命令工具栏,如何自定义Mac终端并使其更有用!

    原标题:如何自定义Mac终端并使其更有用! 终端应用程序是您在macOS中访问命令行的网关.它提供了带有外壳程序或命令解释器的接口,该接口可接收您的命令并调用其他命令来执行例行任务和复杂任务.如果您只 ...

  7. 如何让代码更易于维护_如何轻松地使您的网站更易于访问

    如何让代码更易于维护 by Jaroslav Vaňkát 通过JaroslavVaňkát 如何轻松地使您的网站更易于访问 (How you can easily make your website ...

  8. vim ctrlp_使用Ctrlp和Ctag使Vim更智能

    vim ctrlp by _haochuan 通过_haochuan 使用Ctrlp和Ctag使Vim更智能 (Make Your Vim Smarter Using Ctrlp and Ctags) ...

  9. 虚拟化精华问答 | 虚拟化会使管理更轻松吗?

    戳蓝字"CSDN云计算"关注我们哦! 虚拟化是实现动态IT的重要基石,在虚拟化蓬勃发展的这些年里,虚拟化可以根据不同划分标准进行分类,包括全虚拟化,CPU 虚拟化,硬件虚拟化,服务 ...

最新文章

  1. Linux驱动中,probe函数何时被调用
  2. pip更换源 windows10_Conda及Pip换源处理
  3. sqlcommand对象的有几个操作方法
  4. svo: semi-direct visual odometry 论文解析
  5. 佳能fax_l150如何打印_佳能faxl150说明书下载
  6. substring的用法
  7. 不止 RTC 技术盛会,你还应该知道的声网给开发者的福利
  8. NLP领域首个国家杰青,回归母校!
  9. 反编译DLL。并且修改DLL内容
  10. python(分隔符)
  11. 让Excel 只显示有限行和列
  12. 少年宫计算机活动总结改进措施,少年宫乒乓球的活动总结
  13. 怎么登陆163邮箱?163的邮箱有哪些实用技巧?
  14. [HEVC] HEVC学习(五) —— 帧内预测系列之三
  15. 微信授权能获取那些数据字段,微信授权获取的字段,微信授权能获取到的数据,微信授权
  16. 捕捉生命中的每一道彩虹
  17. 字典dict.pop()和del dict[]的区别与联系
  18. Android LVDS格式(JEIDA与VESA)
  19. java 企业网站源码 后台 springmvc SSM 前台 静态化 代码生成器
  20. 丰度(abundance)

热门文章

  1. ecshop_v2.7.3下载地址
  2. 页面重新跳转到父类url
  3. Atitit.异步编程 java .net php python js 对照
  4. codeforces 435 B. Pasha Maximizes 解题报告
  5. 超级列表框排序mysql_超级列表框List Ctrl
  6. 神经网络与机器学习 笔记—基本知识点(上)
  7. 【Linux 内核】调度器 ④ ( sched_class 调度类结构体分析 | yield_task 函数 | heck_preempt_curr 函数 | task_struct 函数 )
  8. 【ijkplayer】编译 Android 版本的 ijkplayer ④ ( 安装 make yasm 软件 | 执行 compile-ffmpeg.sh all 命令编译 ffmpeg )
  9. 【AOP 面向切面编程】Android Studio 使用 AspectJ 监控方法运行原理分析
  10. 【Android APT】编译时技术 ( 编译时注解 和 注解处理器 依赖库 )