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是可选的,并非所有工作人员都支持。Worker 可以同时支持doCommonAction1and doCommonAction2only 以及doCommonAction1, doCommonAction2and doSpecificAction1, or doCommonAction1, doCommonAction2, doSpecificAction2, 或所有方法。

我还有一个 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
        }
    }
}

很明显,现在我的代码违反了接口隔离原则。我想重构它。好的,我尝试做这样的事情:

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
        }
    }
}

但我认为这段代码看起来很难看。我不确定使用 instanceof 是一个好主意,尤其是因为SpecificAction1AwareInterface根本SpecificAction2AwareInterface不相关WorkerInterface

那么有没有适合我情况的设计模式呢?先感谢您。

4

0 回答 0