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
出现了.
这似乎是一个非常好的设计,适当分离责任.
为了给您提供更多的思考,请考虑工厂将如何决定创建哪种策略.以后当你想要添加另一个策略时,需要改变什么?首先,您要创建一个新的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匹配与视频提供者一起封装的意愿,在添加新策略时保持工厂稳定的愿望,以及添加新策略的速度解决方案.