[英]PHP: How to use extended interfaces without violating SOLID principles in this case?
對於隱晦的標題,我感到非常抱歉,但老實說,我不知道如何以簡短的標題風格來形容它。
第一個簡短版本。 簡單的電子郵件確認機制。 一種方法是發送帶有確認鏈接的電子郵件。 單擊鏈接后,另一個控制器調用第二種方法,該方法從URL驗證令牌。 在這兩個動作之間,將存儲ConfirmationObject以及令牌和其他可能的數據。 成功確認后,將使用“ successHandler”。
簡化代碼:
interface SuccessHandlerInterface {
public function success(ConfirmationObjectInterface $object);
}
class EmailTester {
public function try(ConfirmationObjectInterface $object) {
// some code
}
public function confirm($token) {
$confirmationObject = $this->repository->findByToken($token);
$type = $confirmationObject->getType();
$successHandler = $this->handlersRegistry->getSuccessHandler($type);
$successHandler->success($confirmationObject);
}
}
現在我們將以這種方式使用它:
// Firstly let's implement our own success handler.
class UserRegistrationSuccessHandler implements SuccessHandlerInterface {
public function success(ConfirmationObjectInterface $object) {
// Do some stuff on success.
}
}
// Then let's register this success handler to be available in our `handlersRegistry` object.
$handlersRegistry->addType('user_registration', new UserRegistrationSuccessHandler());
// Now we will extend ConfirmationObjectInterface
interface RegistrationConfirmationObjectInterface extends ConfirmationObjectInterface {
public function getSomeDataGivenOnRegistration();
}
// And at the end, let's try our email
$confirmationObject = new RegistrationConfirmationObject(); // Which implements above interface.
// $confirmationObject->getType() === 'user_registration'
$emailTester->try($confirmationObject);
// Now confirmation link with token is being sent to the given email. If user will click it, below method will be invoked.
$emailTester->confirm($token);
現在的問題是,我希望在成功處理程序中提供RegistrationConfirmationObjectInterface
,而不是ConfirmationObjectInterface
。
我知道我可以做:
// Firstly let's implement our own success handler.
class SuccessHandler implements SuccessHandlerInterface {
public function success(ConfirmationObjectInterface $object) {
if ($object instanceof RegistrationConfirmationObjectInterface) {
// Do stuff
}
}
}
但這感覺不好。 該檢查毫無意義,因為$object
始終是RegistrationConfirmationObjectInterface
的實例。 這種設計有何缺陷,以及如何加以改進?
我不清楚為什么確認對象應實現兩個接口。 從我這里看到的情況來看, RegistrationConfirmationObjectInterface
只有一種方法可以返回某些數據結構,而ConfirmationObjectInterface
根本沒有任何方法。 在這里真的有嚴格的類型安全性嗎,特別是如果您確定自定義的SuccessHandler
將SuccessHandler
接收RegistrationConfirmationObjectInterface
時?
如果ConfirmationObjectInterface
實現不包含任何邏輯,而僅僅是數據結構,則將其替換為關聯數組。 否則,我建議這樣的事情:
interface ConfirmationObjectInterface
{
/**
* @return array
*/
public function getData();
}
class RegistrationConfirmationObject implements ConfirmationObjectInterface
{
public function getData()
{
return ['data specific to registration here'];
}
}
class SomethingElseConfirmationObject implements ConfirmationObjectInterface
{
public function getData()
{
return ['data specific to something else'];
}
}
由於自定義處理程序是特定於具體類型的,因此他們無論如何都會知道期望從getData()
獲得哪些數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.