mercredi 9 décembre 2020

Looking for a design pattern to process or batch process

I have the following structure. Until this point each element could be processed one by one.

interface ProcessingStrategyInterface
{
    public function process(Element $object): string;
}

class SomeListener
{
    /**
     * @var array<string, ProcessingStrategyInterface>
     */
    protected array $processers;

    public function __invoke(DocumentContent $event)
    {
        /**
         * @var array<string, list<Element>> $elements
         */
        $elementGroups = $event->getDynamicElements();

        foreach ($elementGroups as $type => $elements) {
            $processer = $this->processers[$type];

            foreach ($elements as $element) {
                $result = $processer->process($element);
            }
        }

        // [...]
    }
}

Now I have to add a new type of processer which takes the whole list<Element>, and processes them as one, then gives back a string result. For this a new interface could be defined.

interface BatchProcessingStrategyInterface
{
    /**
     * @param list<Element> $elements
     */
    public function batchProcess(array $elements): string;
}

This solution I feel a little bit off:

class SomeListener
{
    /**
     * @var array<string, ProcessingStrategyInterface|BatchProcessingStrategyInterface>
     */
    protected array $processers;

    public function __invoke(DocumentContent $event)
    {
        /**
         * @var array<string, list<Element>> $elements
         */
        $elementGroups = $event->getDynamicElements();

        foreach ($elementGroups as $type => $elements) {
            $processer = $this->processers[$type];

            if ($processer instanceof BatchProcessingStrategyInterface) {
                $result = $processer->batchProcess($elements);
            } else {
                foreach ($elements as $element) {
                    $result = $processer->process($element);
                }
            }
        }

        // [...]
    }
}

I'm wondering if there is a way to solve this in a 100% type-strict way? What I want to achieve is to have single types everywhere by calling them the following way:

class SomeListener
{
    /**
     * @var array<string, ProcessingStrategyInterface>
     */
    protected array $processers;

    public function __invoke(DocumentContent $event)
    {
        /**
         * @var array<string, list<Element>> $elements
         */
        $elementGroups = $event->getDynamicElements();

        foreach ($elementGroups as $type => $elements) {
            $processer = $this->processers[$type];

            $result = $processer->process($elements);
        }

        // [...]
    }
}

Aucun commentaire:

Enregistrer un commentaire