bhittani/dispenser

在纪律化的制度下分配实体

0.3.0 2019-08-24 02:23 UTC

This package is auto-updated.

Last update: 2024-08-24 13:51:24 UTC


README

Travis Build Status Packagist Downloads License

在纪律化的制度下分配实体。

安装

您可以使用 composer 安装此包。

$ composer require bhittani/dispenser --prefer-dist

用法

分配器

其核心是处理函数调用。

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\Dispenser;

$dispenser = new Dispenser(function ($a, $b) {
    return $a . '.' . $b;
});

$dispenser->dispense('foo', 'bar'); // 'foo.bar'

队列分配器

队列分配器维护一个队列中的分配器集合。

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\Queue;
use Bhittani\Dispenser\Dispenser;

$queue = new Queue;

$queue->push(new Dispenser(function ($a, $b) { return $a . $b . 1; }));
$queue->push(new Dispenser(function ($a, $b) { return $a . $b . 2; }));
// Doesn't have to be a dispenser, but recommended.
$queue->push(function ($a, $b) { return $a . $b . 3; });

$queue->dispense('a', 'b'); // ['ab1', 'ab2', 'ab3']

堆栈分配器

堆栈分配器维护一个堆栈中的分配器集合。

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\Stack;
use Bhittani\Dispenser\Dispenser;

$stack = new Stack;

$stack->push(new Dispenser(function ($a, $b) { return $a . $b . 1; }));
$stack->push(new Dispenser(function ($a, $b) { return $a . $b . 2; }));
// Doesn't have to be a dispenser, but recommended.
$stack->push(function ($a, $b) { return $a . $b . 3; });

$stack->dispense('a', 'b'); // ['ab3', 'ab2', 'ab1']

优先级分配器

优先级分配器维护一个优先级堆中的分配器集合。

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\Priority;
use Bhittani\Dispenser\Dispenser;

$priority = new Priority;

$priority->insert(new Dispenser(function ($a, $b) { return $a . $b . 3; }), 1);
$priority->insert(new Dispenser(function ($a, $b) { return $a . $b . 1; }), 3);
// Doesn't have to be a dispenser, but recommended.
$priority->insert(function ($a, $b) { return $a . $b . 2; }, 2);

$priority->dispense('a', 'b'); // ['ab1', 'ab2', 'ab3']

排名与优先级值成正比。在上面的例子中,优先级值为3的分配器首先分配,然后是2,最后是1。

管道分配器

管道允许通过传递先前管道分配器的结果到下一个管道分配器来通过分配器。

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\Stack;
use Bhittani\Dispenser\Pipeline;
use Bhittani\Dispenser\Dispenser;

$pipeline = new Pipeline;

$pipeline->push($stack = new Stack);

$stack->push(new Dispenser(function ($n) { return $n / 5; })); // 100/5=20
$stack->push(new Dispenser(function ($n) { return $n + 60; })); // 40+60=100
$stack->push(function ($n) { return $n * 4; }); // 10*4=40

$pipeline->push(function ($n) { return $n / 2; }); // 20/2=10

$pipeline->dispense(10); // 10

迭代器分配器的纪律将被尊重。即如果我们使用优先级分配器,由于分配顺序的潜在差异,结果可能会变化。

链式分配器

链接受分配器并在链上工作。与管道不同,链中的分配器接收指向链中下一个分配器的处理程序,并且可以通过忽略它来完全停止链的进一步处理。

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\Chain;
use Bhittani\Dispenser\Dispenser;

// Accepts an optional fallback dispenser.
$chain = new Chain(function ($foo, $bar) {
    return '!';
});

$chain->push(new Dispenser(function ($foo, $bar, $next) {
    return '(' . $next($foo, $bar) . ')';
}));

// Doesn't have to be a dispenser, but recommended.
$chain->push(function ($foo, $bar, $next) {
    return $foo.$next($foo, $bar);
});

$chain->push(function ($foo, $bar, $next) {
    return $next($foo, $bar).$bar;
});

$chain->dispense('middle', 'ware'); // (middle!ware)

每个分配器的纪律都将被尊重。即如果我们使用堆栈分配器,由于分配顺序的潜在差异,结果可能会变化。

可以将不同类型的分配器推送到同一个链中。

后备分配器是可选的,并且没有最终的 $next 参数,因为它将是链中的最后一个分配器。

将链式分配器用作 http 中间件

由于链式分配器的强大纪律,我们可以将其用作 http 中间件链。

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\Chain;
use Bhittani\Dispenser\Queue;
use Bhittani\Dispenser\Dispenser;

$chain = new Chain(function ($request) {
    return make_a_response_however_you_want_to($request);
});

$chain->push($middlewares = new Queue);

// With a fictional request & response objects,
// lets record the time spent on the request.
$middlewares->push(new Dispenser(function ($request, $next) {
    $request = $request->startTime();
    $response = $next($request);
    $request->stopTime();

    return $response->withTime($request->getElapsedTime());
}));

$middlewares->push(new Dispenser(function ($request, $next) {
    // Do something...
    return $next($request);
}));

// Handle the $request...
$chain->dispense($request);

创建自定义/扩展分配器

可以通过实现 Bhittani\Dispenser\DispenserInterface 接口来创建扩展分配器。它只有一个必需的方法 dispense,它接受可变数量的参数。这使得它非常简单地将其他分配器混合和利用。力量在您的手中。

示例分配器实现

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Bhittani\Dispenser\DispenserInterface;

class Dispatcher implements DispenserInterface
{
    protected $subscribers = [];

    public function subscribe($key, DispenserInterface $subscriber)
    {
        if (! isset($this->subscribers[$key])) {
            $this->subscribers[$key] = [];
        }

        $this->subscribers[$key][] = $subscriber;

        return $this;
    }

    public function dispense(...$parameters)
    {
        $key = array_shift($parameters);

        if (! isset($this->subscribers[$key])) {
            return [];
        }

        return array_map(function ($subscriber) use ($parameters) {
            return $subscriber->dispense($parameters);
        }, $this->subscribers[$key]);
    }
}

$dispatcher = new Dispatcher;

$dispatcher->subscribe('foo', new Dispenser(function ($a, $b) {
    return $a.'1foo1'.$b;
}));

$dispatcher->subscribe('foo', new Dispenser(function ($a, $b) {
    return $a.'2foo2'.$b;
}));

$dispatcher->subscribe('bar', new Dispenser(function ($a, $b) {
    return $a.'bar'.$b;
}));

$dispatcher->dispense('bar', 'a', 'b'); // ['abarb']
$dispatcher->dispense('foo', 'a', 'b'); // ['a1foo1b', 'a2foo2b']

上面的实现可以作为事件订阅者和发布者工作。

为了可用性,Dispatcher 也在 Bhittani\Dispenser 命名空间下提供。

变更日志

请参阅 CHANGELOG 以获取有关更改的更多信息。

测试

$ git clone https://github.com/kamalkhan/dispenser
$ cd dispenser
$ composer install
$ composer test

贡献

有关详细信息,请参阅 CONTRIBUTINGCONDUCT

安全

如果您发现任何与安全相关的问题,请通过电子邮件 shout@bhittani.com 而不是使用问题跟踪器。

致谢

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件