AgentSkillsCN

acc-create-chain-of-responsibility

为 PHP 8.5 生成责任链模式。以中间件式的组合方式构建请求处理的处理器链,同时附带单元测试。

SKILL.md
--- frontmatter
name: acc-create-chain-of-responsibility
description: Generates Chain of Responsibility pattern for PHP 8.5. Creates handler chains for request processing with middleware-style composition. Includes unit tests.

Chain of Responsibility Pattern Generator

Creates Chain of Responsibility pattern infrastructure for sequential request processing.

When to Use

ScenarioExample
Multiple processorsValidation, discounts, approvals
Unknown handlersPlugin systems
Priority processingFirst match wins
MiddlewareHTTP pipeline, logging

Component Characteristics

HandlerInterface

  • Defines handle method
  • Optional setNext for linking
  • Returns result or delegates

AbstractHandler

  • Implements chain linking
  • Provides base handle logic
  • Simplifies concrete handlers

Concrete Handlers

  • Process specific requests
  • Decide to handle or pass
  • Can terminate or continue chain

Generation Process

Step 1: Generate Handler Interface

Path: src/Domain/{BoundedContext}/Handler/

  1. {Name}HandlerInterface.php — Handler contract with setNext and handle methods

Step 2: Generate Abstract Handler

Path: src/Domain/{BoundedContext}/Handler/

  1. Abstract{Name}Handler.php — Base class with chain linking logic

Step 3: Generate Concrete Handlers

Path: src/Domain/{BoundedContext}/Handler/

  1. {Specific}{Name}Handler.php — Specific handler implementations

Step 4: Generate Chain Builder (Optional)

Path: src/Domain/{BoundedContext}/Handler/

  1. {Name}ChainBuilder.php — Fluent builder for chain construction

Step 5: Generate Tests

  1. {Handler}Test.php — Individual handler tests
  2. {Name}ChainTest.php — Chain integration tests

File Placement

ComponentPath
Handler Interfacesrc/Domain/{BoundedContext}/Handler/
Abstract Handlersrc/Domain/{BoundedContext}/Handler/
Concrete Handlerssrc/Domain/{BoundedContext}/Handler/
Chain Buildersrc/Domain/{BoundedContext}/Handler/
Pipelinesrc/Application/Pipeline/
Unit Teststests/Unit/Domain/{BoundedContext}/Handler/

Naming Conventions

ComponentPatternExample
Interface{Name}HandlerInterfaceValidationHandlerInterface
AbstractAbstract{Name}HandlerAbstractValidationHandler
Concrete{Specific}{Name}HandlerEmailValidationHandler
Builder{Name}ChainBuilderValidationChainBuilder
Test{ClassName}TestEmailValidationHandlerTest

Quick Template Reference

Handler Interface

php
interface {Name}HandlerInterface
{
    public function setNext(self $handler): self;
    public function handle({RequestType} $request): {ResultType};
}

Abstract Handler

php
abstract class Abstract{Name}Handler implements {Name}HandlerInterface
{
    private ?{Name}HandlerInterface $next = null;

    public function setNext({Name}HandlerInterface $handler): {Name}HandlerInterface
    {
        $this->next = $handler;
        return $handler;
    }

    public function handle({RequestType} $request): {ResultType}
    {
        if ($this->next !== null) {
            return $this->next->handle($request);
        }
        return $this->getDefaultResult();
    }

    abstract protected function getDefaultResult(): {ResultType};
}

Concrete Handler

php
final class {Specific}Handler extends Abstract{Name}Handler
{
    public function handle({RequestType} $request): {ResultType}
    {
        if ($this->canHandle($request)) {
            return $this->process($request);
        }
        return parent::handle($request);
    }

    private function canHandle({RequestType} $request): bool
    {
        return {condition};
    }
}

Chain Builder

php
final class {Name}ChainBuilder
{
    private array $handlers = [];

    public function add({Name}HandlerInterface $handler): self
    {
        $this->handlers[] = $handler;
        return $this;
    }

    public function build(): {Name}HandlerInterface
    {
        $first = $this->handlers[0];
        $current = $first;
        for ($i = 1; $i < count($this->handlers); $i++) {
            $current = $current->setNext($this->handlers[$i]);
        }
        return $first;
    }
}

Usage Examples

Validation Chain

php
$chain = (new ValidationChainBuilder())
    ->add(new NotEmptyValidationHandler('email'))
    ->add(new EmailValidationHandler('email'))
    ->add(new MinLengthValidationHandler('password', 8))
    ->build();

$result = $chain->validate($request);

if ($result->hasErrors()) {
    throw new ValidationException($result->getMessage());
}

Discount Chain

php
$vipHandler = new VipDiscountHandler();
$promoHandler = new PromoCodeDiscountHandler($promoCodes);
$bulkHandler = new BulkDiscountHandler();

$vipHandler->setNext($promoHandler);
$promoHandler->setNext($bulkHandler);

$result = $vipHandler->apply($discountRequest);

Anti-patterns to Avoid

Anti-patternProblemSolution
Circular ChainInfinite loopValidate chain structure
No DefaultUnhandled requestsProvide fallback handler
Coupled HandlersHard to reorderUse interface properly
Missing BuilderManual chain assemblyCreate ChainBuilder
State in HandlerNon-reentrantMake handlers stateless

References

For complete PHP templates and examples, see:

  • references/templates.md — Handler Interface, Abstract Handler, Concrete Handler, Chain Builder, Pipeline templates
  • references/examples.md — Validation Chain, Discount Chain examples and tests