如何摆脱它们?我想知道是否存在解决此问题的模式或问题。基本上我需要根据另一个类的type属性实例化一个具体的子类,即如果type = 1则为new A,否则如果type = 2则为new B.等我最终得到了这种工厂在具有type属性的类中:
/**
* 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模型这样做。
答案 0 :(得分:1)
这是replace conditionals by polymorphism非常常见的重构模式。
您可以实施工厂来创建专门的TicketType
并在故障单类型上实施工厂方法,以创建具体的TicketDecorator
和PrivatePage
。
但是,请记住,这确实引入了TicketType
与它创建的具体类之间的耦合。如果最好避免这种耦合,那么坚持你的初始设计。
答案 1 :(得分:1)
嗯,这是我的解决方案。我已将TicketType
(来自原始帖子的类与条件语句)从所有内容中解耦,因此它不知道页面/装饰器。
与此同时,我创建了具体的故障单类:BirthdayTicket
,PartnerTicket
。
我已将工厂方法放入Ticket
类中,该类根据故障单类型生成故障单类的具体实例 - BirthdayTicket
,PartnerTicket
具体的票证类使用上面@plalx建议的多态性来生成我需要的东西(页面,装饰器)。