chippyash / builderpattern
构建模式
Requires
- php: >=5.6
- zendframework/zend-eventmanager: *
Requires (Dev)
Suggests
- zendframework/zend-json: To use the Json Renderer
README
质量保证
上述徽章代表当前的开发分支。一般来说,除非测试、覆盖率和使用性都令人满意,否则我不会向GitHub推送。在短期内这可能不是真的;比如假期、需要为其他下游项目编写代码等。如果您需要稳定的代码,请使用标记版本。阅读“进一步文档”和“安装”。
测试合约(37个测试,65个断言)在docs目录中。
请注意,该库在3.0.0版本中取消了PHP5.5的开发者支持。如果您需要PHP 5.5的支持,请使用版本 >=2,<3
什么?
为PHP提供构建模式的实现。
- 一切都有测试用例
- PHP 5.6+
该库在GNU GPL V3或更高版本许可下发布
如果您已安装PlantUML,您可以在docs文件夹中查看UML图。
请参阅docs文件夹中的测试合约。
为什么?
一次解决问题!要求是有一个构建模式实现,它可以
- 用于构建测试数据集或其他项
- 允许测试脚本通过导演来修改构建器行为
如何?
解决方案将问题分解成部分
- 构建器构建数据集
- 修改器利用事件来传达构建器行为的更改
- 渲染器负责对构建的数据进行一些操作
- 导演控制过程(按照构建模式),并且可以通过修改器与构建器通信
编码基础
请参阅examples文件夹中的示例脚本、构建器和导演。它们演示了使用该库的所有原则。尝试将导演更改为使用不同的渲染器。向构建器添加一些额外的数据项。向构建器添加一个修改项,使用导演的方法允许客户端脚本控制构建。
创建构建器
从AbstractBuilder扩展您的构建器,并添加一个受保护的函数setBuildItems()以将项添加到$$this->buildItems关联数组中。项可以是简单的值持有者或另一个构建器的实现。例如。
protected function setBuildItems() { $this->buildItems = [ 'name' => '', 'createdate' => new \DateTime(), 'account' => new AccountBuilder(), 'exportName => function(){return 'BuilderPattern!';} ]; }
在正常情况下,您可以使用以下方式引用您的构建器项
$builder->itemname = $value $value = $builder->itemname //or $builder->SetItemname($value) $value = $builder->getItemname()
使用set...方法的优势在于它提供了一个流畅的接口,因此可以链接设置器。
在某些情况下,您可能希望在设置和获取时添加一些特殊处理。只需创建一个公开的setItemname($value)方法或getItemname()方法。同样,您可以提供一个hasItemname()方法来覆盖默认的isset()行为。
public function setName($value) { $this->buildItems['name'] = ucfirst($value); return $this; }
您可以通过从AbstractCollectionBuilder扩展来创建集合构建器。在这种情况下,您不需要添加setBuildItems()方法,因为这已经在抽象父类中完成了。
请注意,为集合构建器添加覆盖方法通常没有意义。集合构建器支持将构建器添加到集合中的方法
$cBuilder->addBuilder($builder); $cBuilder->setCollection(array($builder1, $builder2, ...)); $collection = $cBuilder->getCollection()
所有构建器都支持构建和获取结果
if ($builder->build()) { $result = $builder->getResult(); } else { //... }
创建导演
通过扩展AbstractDirector类来创建导演,并提供一个扩展父类的构造函数
class CustomerDirector extends AbstractDirector { public function __construct() { parent::__construct(new CustomerBuilder(), new JsonRenderer()); } }
您可以使用提供的渲染器,或者创建自己的。上面的代码片段是您需要做的最小工作。您可以在构造函数中添加设置步骤。
public function __construct(EventManagerAwareInterface $modifier) { $builder = new CustomerBuilder(); parent::__construct($builder, new JsonRenderer()); //set test account details $builder->setName('Mrs Felicia Bailey'); $builder->account->id = '023197'; }
您还可以添加导演客户可用的方法。
public function setName($name) { $this->builder->setName($name); return $this; } public function setAccountId($id) { $this->builder->account->setId($id); return $this; }
修改构建
该库支持一个基于事件的修改系统,这为您提供了对构建过程的强大控制。默认情况下,构建器不支持此功能。要启用它,您需要在根构建器上调用 setModifier() 方法,这将使其在构建器树中传播。Chippyash\BuilderPattern\Modifier 形式提供了一种股票修改器,但您可以通过实现 Zend\EventManager\EventManagerAwareInterface 来创建自己的修改器,如果需要的话。
如果您在某个大型系统中使用 BuilderPattern,您可能希望在导演之外实例化修改器并传递它,以便事件列车在您的所有应用程序组件之间共享。CustomerDirector 示例就是这样做的。
class CustomerDirector extends AbstractDirector { public function __construct(EventManagerAwareInterface $modifier) { $builder = new CustomerBuilder(); $builder->setModifier($modifier); } }
默认情况下,AbstractDirector 了解并支持两个事件,
- ModifiableInterface::PHASE_PRE_BUILD
- ModifiableInterface::PHASE_POST_BUILD
这些事件分别在构建开始之前和构建成功之后触发。注意:您可以为其他事件创建触发器和监听器。
添加修改器
将修改器(触发器)添加到预构建或后构建触发器堆栈非常简单,只需调用根构建器的 modify() 方法。modify() 预期两个参数
- 一个参数数组,必须至少包含一个 'name' 项,指定所需操作。
- 事件的名称,通常是 ModifiableInterface:l:PHASE_PRE_BUILD 或 ModifiableInterface::PHASE_POST_BUILD,但也可以是任何字符串。
以下是从 CustomerDirector 中的一个示例
public function buyItem($itemId, $amount) { $this->builder->modify( ['name' => 'addPurchase', 'id' => $itemId, 'date' => new \DateTime], ModifiableInterface::PHASE_PRE_BUILD ); $this->builder->modify( ['name' => 'updateBalance', 'amount' => $amount], ModifiableInterface::PHASE_PRE_BUILD ); return $this; }
modify() 方法最好用于两个支持的事件。如果您想触发其他类型的事件,可以直接在事件管理器上调用触发方法。
$modifer->getEventManager()->trigger($eventName, $this, $params);
这允许您拥有极大的控制权,尤其是在您使用构建器作为更大系统的一部分,并且该系统能够在构建实际发生很长时间之前修改最终的构建结果时。
当然,对于每个触发器,您都需要一个或多个监听器。您将这些放在您的构建器类中。在您想要有监听器的构建器中,扩展 setModifier() 方法来设置您的监听器。
public function setModifier(EventManagerAwareInterface $modifier) { parent::setModifier($modifier); $this->modifier->getEventManager()->attach(ModifiableInterface::PHASE_PRE_BUILD, [$this,'preBuildListener']); }
在这个例子中,我们正在告诉事件管理器使用 preBuildListener() 方法来响应预构建触发器。一个典型的实现可能是
public function preBuildListener(Event $e) { if ($e->getParam('name') == 'updateBalance') { $this->balance += $e->getParam('amount'); } }
关于渲染器的注意事项
能够构建某种类型的数据结构是好的,但 BuilderPattern 的真正力量来自于您可以做什么。提供了三个基本的渲染器
- PassthruRenderer - 简单地返回 builder->getResult() 的结果
- JsonRenderer - 返回 builder->getResult() 作为 Json 字符串
- XmlRenderer - 返回 builder->getResult() 作为 XML 定义
您几乎肯定需要创建自己的渲染器,只需实现 RendererInterface。一些想法
- 创建配置对象(尽管这通常通过依赖注入容器处理更好;Symfony 提供了一个很好的示例。然而,BuilderPattern 允许在应用内构建对象,而不是在应用启动时。)
- 通过 SVG 实现创建图表
- 向外部进程发送命令(例如,我已用它来在模拟服务提供商上创建条目以设置系统测试。)
更改库
- 将其分支出来
- 编写测试
- 修改它
- 发起拉取请求
找到了您无法解决的错误吗?
- 将其分支出来
- 编写测试
- 发起拉取请求
注意:在您的拉取请求之前,请确保您已重新合并到 HEAD。
在哪里?
该库托管在 Github 上。它作为 Composable 模块在 Packagist.org 上提供。
安装
安装 [Composer] (https://getcomposer.org.cn/)
对于生产环境
将以下内容添加到你的 composer.json 文件的 "requires" 部分:
"chippyash/builderpattern": ">=3,<4"
对于开发环境
克隆此仓库,然后在本地仓库根目录下运行 Composer 以拉取依赖项。
git clone git@github.com:chippyash/Builder-Pattern.git DataBuilder cd DataBuilder composer install --dev
要运行测试
cd DataBuilder vendor/bin/phpunit -c test/phpunit.xml test/
一些其他内容
查看更多包,请访问 ZF4 Packages
许可证
此软件库根据 BSD 3 Clause 许可证 发布
此软件库的版权为 (c) 2015-2016,Ashley Kitson,英国
此软件库可提供商业许可证,请联系作者。通常,对于值得的公益项目是免费的,但它可以绕过 GPL 许可证的限制,该许可证不允许在商业作品中无限制地包含此代码。
历史
1.0.0 初始版本
1.0.1 集成 Travis 和 Coveralls
1.0.2 完成测试包
1.0.3 添加测试契约
1.1.0 新特性:允许使用闭包作为构建项
1.1.1 使库与 Zend-EventManager 版本无关
2.0.0 BC Break:将命名空间从 chippyash\BuilderPattern 更改为 Chippyash\BuilderPattern
2.0.1 从 Coveralls 迁移到 CodeClimate
2.0.2 添加包链接
2.0.3 验证 PHP7 兼容性
2.0.4 更新构建运行器
2.0.5 更新 composer - 由于 Packagist composer.json 格式更改而强制执行
3.0.0 BC Break. 停止支持旧版 PHP 版本
3.1.0 许可证从 GPL V3 更改为 BSD 3 Clause