前段时间我有完全相同的问题!
我遇到的问题是,每当我偶然发现此问题时,我就会发现我还没有发现一些隐藏的概念。这个概念很可能应该用一些价值对象来表达。您有一个非常抽象的示例,因此恐怕无法证明使用您的代码的含义。但是,这是我个人的做法。我有两个类,它们代表了一种将请求发送到外部资源并解析响应的方法。请求的形成方式和响应的解析方式存在相似之处。这就是我的层次结构:
abstract class AbstractProtocol
{
/**
* @return array Registration params to send
*/
abstract protected function assembleRegistrationPart();
/**
* @return array Payment params to send
*/
abstract protected function assemblePaymentPart();
protected function doSend(array $data)
{
return
(new HttpClient(
[
'timeout' => 60,
'encoding' => 'utf-8',
'language' => 'en',
]
))
->send($data);
}
protected function log(array $data)
{
$header = 'Here is a request to external system!';
$body = implode(', ', $this->maskData($data));
Logger::log($header . '. \n ' . $body);
}
}
class ClassicProtocol extends AbstractProtocol
{
public function send()
{
$registration = $this->assembleRegistrationPart();
$payment = $this->assemblePaymentPart();
$specificParams = $this->assembleClassicSpecificPart();
$dataToSend =
array_merge(
$registration, $payment, $specificParams
);
$this->log($dataToSend);
$this->doSend($dataToSend);
}
protected function assembleRegistrationPart()
{
return ['hello' => 'there'];
}
protected function assemblePaymentPart()
{
return ['pay' => 'yes'];
}
}
这样的代码表明我只是滥用继承。这就是重构的方式:
class ClassicProtocol
{
private $request;
private $logger;
public function __construct(Request $request, Logger $logger, Client $client)
{
$this->request = $request;
$this->client = $client;
$this->logger = $logger;
}
public function send()
{
$this->logger->log($this->request->getData());
$this->client->send($this->request->getData());
}
}
$protocol =
new ClassicProtocol(
new PaymentRequest(
new RegistrationData(),
new PaymentData(),
new ClassicSpecificData()
),
new ClassicLogger(),
new ClassicClient()
);
class RegistrationData
{
public function getData()
{
return ['hello' => 'there'];
}
}
class PaymentData
{
public function getData()
{
return ['pay' => 'yes'];
}
}
class ClassicLogger
{
public function log(array $data)
{
$header = 'Here is a request to external system!';
$body = implode(', ', $this->maskData($data));
Logger::log($header . '. \n ' . $body);
}
}
class ClassicClient
{
private $properties;
public function __construct()
{
$this->properties =
[
'timeout' => 60,
'encoding' => 'utf-8',
'language' => 'en',
];
}
}
从那以后,我非常仔细地对待继承,因为我遭受了很多次伤害。
从那时起,我得出了关于继承的另一个结论。我强烈反对基于内部结构的继承。它破坏了封装,很脆弱,毕竟是程序性的。当我以正确的方式分解域时,继承就很少发生。