根据AppServiceProvider中的模型解析服务

问题描述

给您一个简短的观点:我正在尝试根据条件进行重定向。如果请求满足给定目标的条件,您将重定向到特定目标。

我有Destination模型,该模型具有许多条件(条件模型)。我有很多条件,它们扩展了基本条件模型,例如DateConditionLocationCondition等(通过政治形态关系制成)。每个条件类型都应具有“服务”,以告知给定条件是否匹配请求。示例DateCondition应该具有自己的DateConditionMatcher,该实现实现ConditionMatcherInterface
(仅public function match($condition,$request))。

我想使用SOLID中的Open Closed原理编写它。首先,我想直接向条件模型添加getMatcher()函数,并为每种条件类型返回不同的ConditionMatcher,但是某些ConditionMatchers需要在构造函数中传递其他一些服务,因此这迫使我也将它们注入Condition的模型是很糟糕的。

也许在ServiceProvider中使用上下文绑定可以解决此问题,但如何解决? 我不知道如何将Model耦合到正确的一个ConditionMatcher,然后像这样自由地使用它:

foreach ($destination->conditions as $condition){
       $isMatched = $this->conditionMatcher->match($condition,$request);
}

要始终在$ this-> conditionMatcher下具有正确的ConditionMatcher。 我希望有人能理解我不太清楚的信息。

解决方法

我一夜之间想到了提供服务,以保留所有匹配者。此解决方案的唯一缺点是注入每个匹配器。

class ConditionResolver implements ConditionResolverInterface
{
    /** @var ConditionMatcherInterface[] */
    private $conditionMatchers = [];

    public function __construct(
       DateConditionMatcher $dateConditionMatcher,TimeConditionMatcher $timeConditionMatcher,LocationConditionMatcher $locationConditionMatcher
    ) {
       $this->conditionMatchers[DateCondition::class] = $dateConditionMatcher;
       $this->conditionMatchers[TimeCondition::class] = $timeConditionMatcher;
       $this->conditionMatchers[LocationCondition::class] = $locationConditionMatcher;
    }
}

因此,现在我可以通过这种方式(简化)对给定条件使用正确的匹配器:

foreach ($model->conditions as $condition)
{
    $this->conditionMatchers[get_class($condition)]->match($condition,$request);
}

它允许我将各种服务注入AppServiceProvider中的匹配器。

$this->app->singleton(LocationServiceInterface::class,function($app){
   return new LocationService();
});

$this->app->singleton(DateConditionMatcher::class,function($app){
   return new DateConditionMatcher();
});

$this->app->singleton(TimeConditionMatcher::class,function($app){
   return new TimeConditionMatcher();
});

$this->app->singleton(LocationConditionMatcher::class,function($app){
    return new LocationConditionMatcher($app->make(LocationServiceInterface::class));
});

总的来说,我认为我可以遗漏一些东西,并且可以通过更优雅的方式来完成,但是现在我将其视为答案。如果您有更好的解决方案,请分享:)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...