pugx/godfather
策略模式组件作为库和 symfony2 扩展包
0.1.0
2014-01-20 15:39 UTC
Requires
- php: >=5.3.0
Requires (Dev)
- phpunit/phpunit: 3.7.*
- symfony/dependency-injection: ~2.4
- symfony/framework-bundle: ~2.4
Suggests
- symfony/dependency-injection: if you want to use a proper dependency injection
README
策略模式
http://en.wikipedia.org/wiki/Strategy_pattern
目的
定义一组算法,封装每个算法,并使它们可互换。策略允许算法与使用它的客户端独立变化。
简而言之
给定一个对象,你想知道它的服务。
例如,Entity\Mug
有一个 MugService
,而 Entity\Tshirt
有一个 TshirtService
。
$product = random(0,1)? new Entity\Mug: new Entity\Product $productService = $godfather->getStrategy('service', $product); // also works with $productService = $godfather->getService($product); echo get_class($productService); // will be randomly TshirtService or MugService
沙盒
一个工作示例在 example/godfather.php
cd example
php godfather.php
何时需要像上帝父亲一样的策略家?
- 如果你有很多行为不同的类...
- 如果你有多个条件语句来定义不同的行为...
- 给定一个对象,你想知道它的管理器/服务/处理程序/提供者/存储库...
安装
composer require pugx/godfather ~0.1
一个简单的用例
问题是,你有一个对象,并且你想正确地处理它。
它是如何工作的
这个库并不试图复制服务,或者创建一个新的容器,而是使用别名来建立服务和名称之间的映射。
一个对象通过 Context::getStrategyName
转换,更多信息请参见 更改 Context::Converter。
代码示例
如果你的代码看起来像这样,你需要上帝父亲的保护 :)
// Pseudo Code class Cart function add(ProductInterface $product, OptionsInterface $options) { if ($product instanceOf Mug) { $item = $mugManager->add($options); } if ($product instanceOf Tshirt) { $item = $tshirtManager->add($options); } // ... }
策略家
// Pseudo Code class Cart function add(ProductInterface $product, OptionsInterface $options) { $item = $this->godfather->getManager($product)->add($options); // ... }
GodFather 和数组作为 DIC
$container = new Container\ArrayContainerBuilder(); $container->set('mug_service', new Your\MugService); $container->set('tshirt_service', new Your\TshirtService); $godfather = new Godfather($container, 'godfather'); $godfather->addStrategy('service', 'Mug', 'mug_service'); $godfather->addStrategy('service', 'Tshirt', 'tshirt_service'); // Step2. usage class Cart public function __construct($godfather) //... public function add(ProductInterface $product, OptionsInterface $options) { // get the strategy for cart with the context $product $service = $this->godfather->getStrategy('service', $product); // or $strategy = $this->godfather->getCart($product); return $strategy->addToCart($product, $options); }
GodFather 和 Symfony 依赖注入容器
$container = new Container\ArrayContainerBuilder(); $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.xml'); $godfather = new Godfather($container, 'godfather'); // Step2. usage class Cart public function __construct($godfather) //... public function add(ProductInterface $product, OptionsInterface $options) { // get the strategy for cart with the context $product $service = $this->godfather->getStrategy('service', $product); // or $strategy = $this->godfather->getService($product);
使用 Symfony2 扩展包
安装扩展包
在 app/AppKernel.php
中添加扩展包
class AppKernel extends Kernel { public function registerBundles() { $bundles = array( ... new PUGX\GodfatherBundle\GodfatherBundle(),
配置 app/config/config.yml
最小配置
# add the below configuration only if you need to specify the fallback or the interface. godfather: default: contexts: manager: ~ # your strategy name
使用后备策略
# add the below configuration only if you need to specify the fallback or the interface. godfather: default: contexts: manager: fallback: manager_standard # need a reference to a defined service
设置您的策略
parameters: mug.class: Mug tshirt.class: Tshirt services: manager_standard: class: StandardProductManager manager_mug: class: MugManager tags: - { name: godfather.strategy, context_name: 'manager', context_key: %mug.class% } manager_tshirt: class: TshirtManager tags: - { name: godfather.strategy, context_name: 'manager', context_key: %tshirt.class% }
在控制器中使用
$product = new \Product\ShoeProduct(); $manager = $container->get('godfather')->getManager($product); // or $manager = $container->get('godfather')->getStrategy('manager', $product); // then $manager->doSomethingGreat();
使用多个实例的高级功能
除了默认设置外,您还可以在不同的上帝父亲实例中配置策略。
godfather: death: contexts: manager: ~ life: contexts: manager: ~
策略
services: manager.entity_life: class: EntityProductManager arguments: ['life'] tags: - { name: godfather.strategy, instance:'life', context_name: 'manager', context_key: %product.show.class% } manager.entity_death: class: EntityProductManager arguments: ['death'] tags: - { name: godfather.strategy, instance:'death', context_name: 'manager', context_key: %product.show.class% }
然后是具有多个实例的代码
$this->getContainer('godfather.life')->getManager($entity); $this->getContainer('godfather.death')->getManager($entity);
更改 Context::Converter
Godfather\Context\Context::getStrategyName
将对象转换为策略名称,默认转换仅从 $object 中提取短类名。
如果您想要另一个转换器,创建一个扩展 ContextInterface 的类,然后
godfather: deafault: contexts: manager: class: \My\Context
贡献
积极的贡献和补丁非常受欢迎。为了保持事物的形状,我们有一系列单元测试。如果您正在提交拉取请求,请确保它们仍在通过,如果您添加了功能,请查看覆盖率,它应该相当高 :)
composer create-project pugx/godfather --dev -s dev
cd godfather
bin/phpunit