インターフェースがあるとします:
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
のみ、doCommonAction1
、doCommonAction2
and 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
}
}
}
私のコードがインターフェイス分離の原則に違反していることは明らかです。私はそれをリファクタリングしたいと思います。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
。
私の状況に適したデザインパターンはありますか?前もって感謝します。