这是策略模式的一个很好的用例吗?

JCM*_*JCM 4 php language-agnostic design-patterns strategy-pattern factory-pattern

我正在使用需要接收多个视频的应用程序,并将其显示在特定页面上,目前这些视频只能来自YouTube,因为实现不允许其他提供商,因为获取视频数据的代码作为预览图像,直接放置在负责显示视频的View Helper中.

我想改变这种结构,可以很容易地添加新的供应商,如Vimeo的,我认为策略模式将是理想的,我会在我的视图助手的方法setVideoUrl( string $url ),这种方法会调用该方法getProviderStrategy( string $url )class VideoProviderFactory,这然后,工厂类将返回策略类(如果可用),该类interface VideoProvider为视频URL的提供者实现.

你怎么看?这是对的?我需要改变什么?

细节:我最初考虑过将一个开关直接选择到View Helper中,但在阅读完这个问题之后:我没有'switch'语句的策略模式?我看到我错了,然后class VideoProviderFactory出现了.

Jor*_*dão 5

这似乎是一个非常好的设计,适当分离责任.

为了给您提供更多的思考,请考虑工厂将如何决定创建哪种策略.以后当你想要添加另一个策略时,需要改变什么?首先,您要创建一个新的VideoProvider,然后您必须更改工厂switch语句(如您所述)并包含此新策略的选择逻辑.现在,这在大多数情况下都非常好,但是如果你想在不改变工厂的情况下添加新策略呢?

一种方法是使用类似工厂的接口,该接口具有基于URL决定是否应该创建特定的方法VideoProvider; 让我们称之为VideoProviderMatcher(伪代码):

interface VideoProviderMatcher {
  bool understands(url)
  VideoProvider create()
}
Run Code Online (Sandbox Code Playgroud)

现在,此接口知道它是否理解URL以及如何创建与其相关的URL VideoProvider.当您需要创建新策略时,您实现VideoProvider了相关和相关的策略VideoProviderMatcher.对于工厂,它更改为VideoProviderMatcher使用责任链(伪代码)将s和委托的列表封装到第一个理解给定URL 的列表:

class VideoProviderFactory {
  List[VideoProviderMatcher] matchers
  void registerMatcher(VideoProviderMatcher matcher) {
    matchers.add(matcher)
  }
  VideoProvider getVideoProviderFor(url) {
    foreach (matcher in matchers) {
      if (matcher.understands(url)) return matcher.create()
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

现在唯一需要更改的代码是首先创建工厂的代码.理想情况下,它有一个VideoProviderMatcher用于填充工厂的s 列表,您只需将另一个项添加到列表中.

现在,这值得吗?我要说这取决于匹配逻辑的复杂性,将URL匹配与视频提供者一起封装的意愿,在添加新策略时保持工厂稳定的愿望,以及添加新策略的速度解决方案.