工厂中的重复条件语句
Duplicate conditional statements in the factory
如何摆脱它们?我想知道是否有解决此问题的模式或方法。基本上我需要根据另一个 class 的类型 属性 实例化一个具体的 child class,即如果 type=1 那么 new A,否则如果 type=2 那么 new B 等。我在 class 中得到了这种类型为 属性:
的工厂
/**
* 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));
}
}
工厂中的每个方法都测试类型字段,这对我来说看起来很笨拙。我想为每种类型都有一个单独的 child class 并使用没有条件语句的工厂方法,但我不能用 Laravel 模型这样做。
这是 replace conditionals by polymorphism 的一种非常常见的重构模式。
您可以只实现一个工厂来创建专门的 TicketType
s 并在票据类型上实现工厂方法来创建具体的 TicketDecorator
和 PrivatePage
。
但是,请记住,这确实会在 TicketType
和它创建的具体 类 之间引入耦合。如果最好避免这种耦合,请坚持您的初始设计。
好吧,这是我的解决方案。我已经将 TicketType
(class 从带有条件语句的原始 post 中分离出来),因此它不知道 pages/decorators.
同时我创建了具体的工单 classes: BirthdayTicket
, PartnerTicket
.
我在 Ticket
class 中放置了一个工厂方法,它根据票证的类型生成票证的具体实例 class - BirthdayTicket
,PartnerTicket
等。具体票证 classes 使用上面@plalx 建议的多态性生成我需要的东西(页面、装饰器)。
如何摆脱它们?我想知道是否有解决此问题的模式或方法。基本上我需要根据另一个 class 的类型 属性 实例化一个具体的 child class,即如果 type=1 那么 new A,否则如果 type=2 那么 new B 等。我在 class 中得到了这种类型为 属性:
的工厂/**
* 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));
}
}
工厂中的每个方法都测试类型字段,这对我来说看起来很笨拙。我想为每种类型都有一个单独的 child class 并使用没有条件语句的工厂方法,但我不能用 Laravel 模型这样做。
这是 replace conditionals by polymorphism 的一种非常常见的重构模式。
您可以只实现一个工厂来创建专门的 TicketType
s 并在票据类型上实现工厂方法来创建具体的 TicketDecorator
和 PrivatePage
。
但是,请记住,这确实会在 TicketType
和它创建的具体 类 之间引入耦合。如果最好避免这种耦合,请坚持您的初始设计。
好吧,这是我的解决方案。我已经将 TicketType
(class 从带有条件语句的原始 post 中分离出来),因此它不知道 pages/decorators.
同时我创建了具体的工单 classes: BirthdayTicket
, PartnerTicket
.
我在 Ticket
class 中放置了一个工厂方法,它根据票证的类型生成票证的具体实例 class - BirthdayTicket
,PartnerTicket
等。具体票证 classes 使用上面@plalx 建议的多态性生成我需要的东西(页面、装饰器)。