假设我有一个接口:
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 可以同时支持doCommonAction1
and doCommonAction2
only 以及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
}
}
}
很明显,现在我的代码违反了接口隔离原则。我想重构它。好的,我尝试做这样的事情:
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
。
那么有没有适合我情况的设计模式呢?先感谢您。