哪个是我的PHP应用程序的正确设计模式?

时间:2012-06-27 23:55:34

标签: php regex oop design-patterns

我一直在努力寻找实现我的系统的好方法,该系统基本上匹配字符串中节目的季节和剧集编号,您可以在此处查看当前的工作代码:https://github.com/huddy/tvfilename

我目前正在重写这个库,并想要一种更好的方法来实现匹配的发生方式,目前基本上是它的工作方式:

有一个包含类的文件夹(称为处理程序),每个处理程序都是一个实现接口的类,以确保一个名为match()的方法;存在,此匹配方法使用存储在该处理程序类(其中有很多)的属性中的正则表达式来尝试匹配季节和剧集。

该类通过将每个处理程序实例化为存储在属性中的数组来加载所有这些处理程序,当我想尝试匹配一些字符串时,方法迭代这些对象调用match();然后在结果集中返回返回true的第一个,其中匹配的季节和剧集。

我真的不喜欢这种做法,这对我来说很苛刻,我希望设计模式可以提供帮助,我的最终目标是使用最佳实践做到这一点,我想知道我应该选择哪一个使用?

存在的其他问题是:

  • 多个处理程序可以匹配一个字符串,所以它们必须按顺序防止更贪婪的字符串首先匹配,不确定这是否可以解决,因为一些正则表达式模式必须是贪婪的,但是可能是一个得分系统,显示比赛正确的可能性的百分比,我不知道如何实际实现这一点。

  • 我不是在实例化所有这些处理程序是一种很好的方法,速度很重要,但使用最佳实践并坚持设计模式来创建良好,可扩展和可维护的代码是我的最高优先级。值得注意的是,处理程序类有时会执行除正则表达式匹配之外的其他操作,它们有时会通过删除常用单词等来准备要匹配的字符串。

为任何帮助干杯 比利

4 个答案:

答案 0 :(得分:2)

为每个regexp创建一个类是非常低效的,你在这里混淆带有数据的类。您可以将所有正则表达式存储在配置数组或单独的类或XML文件中 - 无关紧要。然后,单个方法可以接受所有正则表达式,迭代它们并执行匹配。 如果季节不总是匹配[1],你可以使用命名的子模式 - 这将解决这个问题。

至于你的模式问题顺序,你可以简单地按照你喜欢的顺序放置所有模式 - 从大多数模式到更一般的模式。

答案 1 :(得分:1)

您可以将此pattern to implement complex case analysis改编为PHP。这或多或少都是你一直在做的事情。您定义了所有案例,实现了一个条件,该条件说明何时适用,以及如何在案例中解决问题。该模式将允许您决定在多个案例适用时做什么(选择一个,给一个偏好而不是另一个,或任何你想要的)。

如果你为S01E01命名你的格式更好,我也是个好主意

SddEdd
SnnEnn
SDigitDigitEDigitDigit
STwoDigitsETWoDigits

而不是format1,format2。 您还可以稍微修改模式以使用对象实例来处理案例的条件和解决方案,这样您就可以使用单个类来处理RegExps案例 新的RegexpCase(“S(?:\ d {2})E(?:\ d {2})”); 以及所有其他不仅仅是使用类的正则表达式来解决这种情况的情况。

答案 2 :(得分:0)

我认为您需要根据所需参数订购模式订单。 我认为第二个答案真的很好地回答了你的问题。你似乎也很好地处理了你的代码。它似乎很好写了

答案 3 :(得分:0)

我个人更喜欢在这个实例中使用单独的类,如果采用这种方法,你的代码库将更加灵活(即如果你真的需要操作字符串)。如果你看一下Zend如何实现Zend_Validate和Zend_Filter,它们对当前实现有一个非常类似的方法(循环运行属性 - > validate()和 - > filter())。

我的结构与此类似:

  • App_Tv_Match
  • App_Tv_Match_Abstract
  • App_Tv_Match_Collection
  • App_Tv_Match_SXXEXX
  • App_Tv_Match_SeasonXEpisodeX

(但是你的命名可能会对课程造成刺激)。

然而,在摘要中我会有类似的设置:

Abstract Class App_Tv_Match_Abstract
{
     protected $_returnOnMatch = false;
     protected $_priority      = 1;
}

我的App_Tv_Match_Collection类会注入匹配类 - 然后集合类将使用匹配类处理排序和匹配。如果Match类的“returnOnMatch”标记为true,那么如果匹配,我会停止尝试并返回这个(即非贪婪的),但是如果没有returnOnMatch类匹配那么我将返回具有最高优先级的那个(或者使用排序或集合类中的简单循环。)