pugx/godfather

策略模式组件作为库和 symfony2 扩展包

0.1.0 2014-01-20 15:39 UTC

This package is auto-updated.

Last update: 2024-09-18 23:27:32 UTC


README

  1. 策略模式
  2. 安装
  3. Symfony2 扩展包
  4. 贡献

travis-ci Latest Stable Version Total Downloads Latest Unstable Version

策略模式

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

许可证

许可证可见于此处.