2016-10-28 3 views
0

どうすれば削除できますか?私は、この問題に対処するパターンや何かがあるかどうか疑問に思っています。基本的には別のクラスのtypeプロパティに基づいて具体的な子クラスをインスタンス化する必要があります。つまりtype = 1、new A、type = 2ならnew Bなどです。タイププロパティを持つクラス:工場出荷時に重複している条件文

/** 
* Get a ticket decorator based on the ticket type 
* @return ReferralService\TicketDecorator 
* @throws Exception 
*/ 
public function getTicketDecorator(): ReferralService\TicketDecorator 
{ 
    if (!$this->code) { 
     throw new Exception("Couldn't create a ticket wrapper based on the type without a code"); 
    } 

    /** 
    * The debug service 
    * @var Debug\Service $debugService 
    */ 
    $debugService = app(Debug\Service::class); 
    $debugService->setDebug(config('referral.debug')); 

    switch ($this->code) { 
     case self::TYPE_FEEDBACK: 
      return new ReferralService\TicketDecorator\FeedbackTicketDecorator($debugService); 
      break; 
     case self::TYPE_BIRTHDAY: 
      return new ReferralService\TicketDecorator\BirthdayTicketDecorator($debugService); 
      break; 
     case self::TYPE_NEW_PARTNER: 
      return new ReferralService\TicketDecorator\PartnerTicketDecorator($debugService); 
      break; 
     default: 
      throw new Exception(sprintf("Couldn't instantiate a ticket decorator based on the %s type", $this->code)); 

    } 
} 

/** 
* Instantiate a private page based on the ticket type 
* @param ReferralService\Service $service 
* @param Referrer $referrer 
* @param Ticket $ticket 
* @return ReferralService\Page\PrivatePage 
* @throws Exception 
*/ 
public function getPrivatePage(ReferralService\Service $service, Referrer $referrer, Ticket $ticket): ReferralService\Page\PrivatePage 
{ 
    if (!$this->code) { 
     throw new Exception("Couldn't create a private page based on the type without a code"); 
    } 

    switch ($this->code) { 
     case self::TYPE_FEEDBACK: 
      return new ReferralService\Page\PrivatePage\EmailReference($this->service, $referrer, $ticket); 
      break; 
     case self::TYPE_BIRTHDAY: 
      return new ReferralService\Page\PrivatePage\Birthday($this->service, $referrer, $ticket); 
      break; 
     case self::TYPE_NEW_PARTNER: 
      return new ReferralService\Page\PrivatePage\Partner($this->service, $referrer, $ticket); 
      break; 
     default: 
      throw new Exception(sprintf("Could't find a page for the type", $this->code)); 
    } 
} 

工場のすべてのメソッドがタイプフィールドをテストしますが、これは私にとっては不思議です。私は、すべての型に対して独立した子クラスを持ち、条件文を使わずにファクトリメソッドを使うことを考えましたが、Laravelモデルではできません。

+1

それはそれほど美味しくはありませんが、何も問題はありません。それは、工場を持っている、かなり読みやすい正当な方法です。私はそれについてあまり心配しないでください – Andrew

+0

あなたはすでにすべての無駄な 'break;'( 'return'sの後)を削除することができます。 –

+0

@Casimir right、私はちょうどbreakステートメントをいつも使っていました。 – Sergey

答えて

1

これは、非常に一般的なリファクタリングパターンreplace conditionals by polymorphismです。

TicketTypeを作成し、チケットタイプにファクトリメソッドを実装して具体的なTicketDecoratorPrivatePageを作成するファクトリを実装するだけでよいでしょう。

しかし、これはTicketTypeとそれが作成する具体的なクラスの間の結合を導入することに注意してください。このようなカップリングを避けることが望ましい場合は、最初のデザインに固執してください。

+0

なぜ誰もそのようなカップリングを避けたいですか? – Sergey

+0

@Sergey主に、抽象化のレベルとモジュール間の結合に依存します。例えば。'Product'モジュールが' Product'モジュールにあって、そのタイプが 'Shipping'モジュールで配送戦略を選択するのに使われているなら、' Shipping'に 'Product'を' Shipping'に結合することを避けたいでしょう。プロダクトに結合されるべきである。最良の例ではありませんが、うまくいけばそれはあなたにとって理にかなっています。 – plalx

+0

はい、ありがとうございます。多態性を使って具体的なページとデコレータを生成する抽象ファクトリをオーバーライドする具体的なクラスの1つを選ぶTicketTypeクラスの中で、おそらくファクトリメソッドを実行します。それはあなたの答えとは少し異なりますが、それでもほとんど同じです。 – Sergey

1

これは私の解決策です。私はTicketType(元の投稿から条件文を含むクラス)をすべてから切り離して、ページ/デコレータを認識しないようにしました。

同時に、具体的なチケットクラス:BirthdayTicket,PartnerTicketを作成しました。

私はチケットのタイプに基づいて、チケットクラスの具体的なインスタンスを生成Ticketクラスにファクトリメソッドを配置した - 具体的なチケットのクラスは、私は(ページ、デコレータ)必要なものを作るなどPartnerTicketBirthdayTicket使用上記の@plalxで示唆される多型。

関連する問題