簡體   English   中英

PHP:在這種情況下,如何使用擴展接口而不違反SOLID原則?

[英]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根本沒有任何方法。 在這里真的有嚴格的類型安全性嗎,特別是如果您確定自定義的SuccessHandlerSuccessHandler接收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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM