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
意图
定义一系列算法,封装每个算法,并使它们可互换。策略允许算法独立于使用它的客户端而变化。
TL;DR
给定一个对象,你想要知道它的服务。
例如,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