2016-07-22 8 views
2

私は非常識なタイトルのために申し訳ありませんが、私は正直なところ、短いタイトルスタイルの方法でそれを表現する方法を知らない。PHP:この場合、SOLID原則に違反することなく拡張インターフェースを使用する方法は?

最初の短いバージョン。簡単な電子メールの確認の仕組み。 1つの方法は、確認リンク付きで電子メールを送信することです。リンクをクリックすると、別のコントローラが第2のメソッドを呼び出し、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のインスタンスになるため、このチェックは無意味です。このデザインにはどのような欠陥があり、どのように改善することができますか?

+0

私はここで間違った終わりを得ているかもしれませんが、あなたはインターフェースをインスタンス化しないので、このようなことは私にはあまり意味がありません: 'public function success(ConfirmationObjectInterface $ object)' < - それはインターフェイスまたはオブジェクト(クラスインスタンス)? – CD001

+0

@ CD001渡されたオブジェクトに強制的にインターフェイスを実装させます。そうしないと、PHPによってエラーがスローされます。 –

+0

@FélixGagnon-Grenierは実際に動作しますか? – CD001

答えて

0

確認オブジェクトが2つのインターフェイスを実装する必要がある理由は、私には不明です。ここからわかるように、RegistrationConfirmationObjectInterfaceにはデータ構造体を返すメソッドが1つしかなく、ConfirmationObjectInterfaceにはメソッドがまったくありません。厳密なタイプセーフティが本当に必要ですか?特に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()から期待するものを知っているだろう。そうでなければ、私はこのような何かを示唆しています。

+0

これは簡単なコードです。 'ConfirmationObjectInterface'は実際には例えば" getType "、" getEmail "や" getToken "のような独自のメソッドを持っています。私の現在の実装は実際に連想配列に依存しています。なぜなら、私はこの問題をより良く解決できなかったからですが、本当に他の方法はないのだろうかと思っていました。 –

+0

「良い」とはどういう意味ですか?超厳密なタイプの安全性は常に良いとは限りません。 'ConfirmationObjectInterface'のすべてのメソッドがゲッターである場合、これらのオブジェクトは実際にはデータ構造であり、実際にはインタフェースである必要はありません。インターフェースの目的は、「どのように」から「どのように」抽象化することであり、単純なものの余分なインターフェースを作成するだけで複雑さが増し、実際の問題は解決されません。 –

+0

これは良い点です。私は、この特定のプロジェクトを限界へのインターフェースの導入、それが意味をなさない時を見て、自分の理解を向上させるようにしました。私はあなたの答えを考えて、それが正しければ、私は完全にそれを受け入れるだろう:)。 –

関連する問題