1

インターフェースがあるとします:

interface WorkerInterface
{
    public function doCommonAction1(CommonAction1Params $params): CommonAction1Result;

    public function doCommonAction2(CommonAction2Params $params): CommonAction2Result;

    /**
     * @return void
     *
     * @throws UnsupportedMethodException
     */
    public function doSpecificAction1(SpecificAction1Params $params): SpecificAction1Result;

    /**
     * @return void
     *
     * @throws UnsupportedMethodException
     */
    public function doSpecificAction2(SpecificAction2Params $params): SpecificAction2Result;
}

問題は、メソッドdoSpecificAction1とメソッドdoSpecificAction2がオプションであり、すべてのワーカーでサポートされているわけではないことです。ワーカーはdoCommonAction1、 anddoCommonAction2のみ、doCommonAction1doCommonAction2and doSpecificAction1、 or doCommonAction1doCommonAction2doSpecificAction2、またはすべてのメソッドをまとめてサポートできます。

また、WorkerFactory があります。

class WorkerFactory
{
    public function createWorker(string $workerId): WorkerInterface
    {
        // worker is created here
    }
}

それから私はコントローラーを持っています:

class ActionController {
    public function commonAction1(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        $worker->doCommonAction1(new CommonAction1Params());
    }

    public function commonAction2(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        $worker->doCommonAction2(new CommonAction2Params());
    }

    public function specificAction1(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        try {
            $worker->doSpecificAction1(new SpecificAction1Params());
        } catch (UnsupportedMethodException $e) {
            // do something
        }
    }

    public function specificAction2(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        try {
            $worker->doSpecificAction2(new SpecificAction2Params());
        } catch (UnsupportedMethodException $e) {
            // do something
        }
    }
}

私のコードがインターフェイス分離の原則に違反していることは明らかです。私はそれをリファクタリングしたいと思います。OK、私はこのようなことをしてみます:

interface WorkerInterface
{
    public function doCommonAction1(CommonAction1Params $params): CommonAction1Result;

    public function doCommonAction2(CommonAction2Params $params): CommonAction2Result;
}

interface SpecificAction1AwareInterface
{
    public function doSpecificAction1(SpecificAction1Params $params): SpecificAction1Result;
}

interface SpecificAction2AwareInterface
{
    public function doSpecificAction2(SpecificAction2Params $params): SpecificAction2Result;
}

したがって、私のワーカーは次のようになります。

class Worker1 implements WorkerInterface {}

class Worker2 implements WorkerInterface, SpecificAction1AwareInterface {}

class Worker3 implements WorkerInterface, SpecificAction1AwareInterface, SpecificAction2AwareInterface {}

そして今、私のコントローラーはこれに変わります:

class ActionController {
    public function commonAction1(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        $worker->doCommonAction1(new CommonAction1Params());
    }

    public function commonAction2(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        $worker->doCommonAction2(new CommonAction2Params());
    }

    public function specificAction1(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        if ($worker instanceof SpecificAction1AwareInterface) {
            $worker->doSpecificAction1(new SpecificAction1Params());
        } else {
            // do something
        }
    }

    public function specificAction2(string $workerId, WorkerFactory $factory)
    {
        $worker = $factory->createWorker($workerId);

        if ($worker instanceof SpecificAction2AwareInterface) {
            $worker->doSpecificAction1(new SpecificAction2Params());
        } else {
            // do something
        }
    }
}

しかし、このコードは醜いように思えます。SpecificAction1AwareInterface特にandSpecificAction2AwareInterfaceはまったく関係がないため、 instanceof を使用することが良い考えであるかどうかはわかりませんWorkerInterface

私の状況に適したデザインパターンはありますか?前もって感謝します。

4

0 に答える 0