4

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

我想更改此结构以方便添加新的提供程序,例如 Vimeo,并且我认为 Strategy 模式将是理想的,我将在我的 View Helper 中有方法setVideoUrl( string $url ),此方法将从中调用方法getProviderStrategy( string $url )class VideoProviderFactory这然后,工厂类将返回(如果可用)interface VideoProvider为视频 url 的提供者实现 , 的策略类。

你怎么看?这是对的?我需要改变一些东西吗?

细节:我最初考虑在 View Helper 中直接放置一个选择策略的开关,但在阅读了这个问题后:I Strategy Pattern with no 'switch' statements?我看到我错了,然后class VideoProviderFactory出现了。

4

1 回答 1

5

这看起来是一个非常好的设计,具有适当的职责分离。

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

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

interface VideoProviderMatcher {
  bool understands(url)
  VideoProvider create()
}

现在,这个接口知道它是否理解一个 URL 以及如何创建与之VideoProvider相关的 URL。当您需要创建新策略时,您需要同时实施VideoProvider和相关的VideoProviderMatcher. 至于工厂,它使用责任链(伪代码)封装了一个VideoProviderMatchers 列表并委托给第一个理解给定 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()
    }
  }
}

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

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

于 2012-04-16T04:10:24.673 回答