Php 构造函数注入vs setter工厂

Php 构造函数注入vs setter工厂,php,design-patterns,Php,Design Patterns,我有一个类搜索引擎,它可以有不同的行为,因此我需要传递一个搜索策略对象。目前我在搜索引擎中有一个setter方法,它由一个SearchStrategyFactory 我的问题是,在方法中使用工厂类来获取对象是否是一种糟糕的设计 我知道我最好通过构造函数传递策略,或者作为setter方法中的一个参数 但我知道,我避免了大量嵌套的if语句 当然,任何建议都是值得赞赏的。如果简单的依赖注入是一种可行的替代方案,我不喜欢工厂方法 更糟糕的是,您不仅在自己的搜索引擎类中使用工厂模式,而且还使用定位器模式来

我有一个类搜索引擎,它可以有不同的行为,因此我需要传递一个搜索策略对象。目前我在搜索引擎中有一个setter方法,它由一个SearchStrategyFactory

我的问题是,在方法中使用工厂类来获取对象是否是一种糟糕的设计

我知道我最好通过构造函数传递策略,或者作为setter方法中的一个参数

但我知道,我避免了大量嵌套的if语句


当然,任何建议都是值得赞赏的。

如果简单的依赖注入是一种可行的替代方案,我不喜欢工厂方法

更糟糕的是,您不仅在自己的搜索引擎类中使用工厂模式,而且还使用定位器模式来创建它

我认为这个代码设计不好是因为:

  • 通过使您的策略可变,您很难对搜索引擎使用的当前方法进行推理
  • 通过使用定位器模式,您将引入第二个依赖项。战略和容器的关系。所有这些都失去了模块性,因为构建逻辑现在部分地与您自己的搜索引擎实现相关联
我建议您使用依赖注入。使策略不变。如果需要策略是可变的,请使用接受策略实例的setter,而不是策略类字符串


如果您在构建过程中注意到,您有一组分支逻辑来决定实例化;您可能没有充分利用DI的潜力。将逻辑转移到setter以消除if语句可能会引入更严重的错误,因为分支将发生在代码库中的任何地方,这使得对当前策略进行推理变得更加困难。

因此,这个问题可能更适合于。但是当它在这里的时候:你的目标不应该总是有一个策略吗?在这种情况下,构造函数注入的值最有意义。我的意思是注入strategy对象本身(构造函数可以始终将其作为可选参数,如果它为null,则使用工厂生成一个参数,如果您确实需要的话)。如果您希望SearchEngine的同一实例能够使用不同的策略进行搜索,您是否可以让搜索方法获取一个实现策略接口的对象,或者是否有其他原因使搜索引擎需要一个策略,而不仅仅是将其用于搜索()?另一方面,如果搜索引擎的每个实例只使用一种策略,则构造函数注入似乎很好。@Jeto Yes搜索引擎将始终有一种策略。首先我实例化SearchEngine对象,然后设置策略。关于策略本身的注入,我现在这样做的原因是因为我有3个变量可以确定最终的SearchStrategy,这意味着许多if语句,其中一些是嵌套的。@Jeto为了避免嵌套if语句,我尝试将if语句分解成单独的策略族。搜索引擎的存在是为了破坏if语句。因此,基于3个变量中的1个,我创建了一个搜索引擎(我有2种类型的搜索引擎),这样我就摆脱了嵌套的if语句。然后根据其他两个变量(这两个变量在SearchStrategyFactory中),我决定对给定的搜索引擎使用哪种搜索策略。@Don’t根据用户的请求,搜索引擎的每个实例都可以使用不同的策略。如果用户想要搜索苹果,则使用AppleStategy,依此类推。谢谢您的回答。为了说明我对if语句的最初问题,如果你看一下我的另一个问题(在给定的链接上),你可以在这里找到它,我有3个变量来决定搜索策略。$searchQuery if语句被搜索引擎替换。通过这种方式,我打破了一个嵌套的if语句,创建了一个SearchStrategyFactory,负责处理其他2个变量,以确定SearchStrategyDear@OrestisuRic,我查看了代码,除了我之前关于依赖项注入的评论外,我认为这些if语句没有问题。代码非常明显,可以理解。我看不出您如何能够在不显著降低易读性和可维护性的情况下使用任何其他技术。我知道你可能不喜欢if语句,但在我看来,将多态性与动态问题联系起来也不是一个好办法,4 if语句甚至可以与monkeys head亲爱的@Transitive结合起来,再次感谢你的回复。也许我无缘无故地把事情搞得太复杂了。亲爱的@Transitive从您看到的代码来看,在另一个工厂中调用工厂有意义吗(当然这只是隐藏了另一个类中的if语句)
class SearchEngine
{
    protected $strategy;

    public function setStrategy($type)
    {
          $this->strategy = app(SearchStrategyFactory::class)->create($type);
    }

    public function search()
    {
         return $this->strategy->search();
    }

}