Php 如何避免大开关语句?

Php 如何避免大开关语句?,php,design-patterns,Php,Design Patterns,我有一个内部应用程序,其中一个函数包含太多的开关盒 这是用php开发的。这个特定的函数用于将更改写入数据库,还用于保存单个字段值的历史记录。所以它对每个领域都有一个案例,因为不同的领域需要应用不同的东西 switch ($item){ case 'item1': do_something(); case 'item2': do_something_different(): } 在这种情况下,是否有一种设计模式可以遵循。每个项目

我有一个内部应用程序,其中一个函数包含太多的开关盒

这是用php开发的。这个特定的函数用于将更改写入数据库,还用于保存单个字段值的历史记录。所以它对每个领域都有一个案例,因为不同的领域需要应用不同的东西

switch ($item){  
    case 'item1':  
        do_something();  
    case 'item2':  
        do_something_different():  
}
在这种情况下,是否有一种设计模式可以遵循。每个项目的函数看起来也不太适合未来

更新:

通过该示例,您并没有透露太多关于代码的信息,但另一种选择是使用状态机。您可以获取一个数组,并将项名称指定为键,值将是函数

$machine = array('item1' => do_something, 'item_2' => do_something_different);
$machine['item1']();
然后,它甚至为可插拔性而开放,您可以在其中包含一个文件,其中说明:

$machine['item3'] = do_something_else_else;

这不是一个好功能。它应该有三个功能,
edit\u name
edit\u manager
edit\u liscencedata
。您可以将案例之间重复的所有内容移动到您应该定义的
Change
类的构造函数中。

从代码片段中可以看出,您面临的是一个非常严重的责任混杂的情况,以及由于缺少分解而复制粘贴编码的情况。您的编辑函数处理至少三个不同层上的内容以及三个不同的对象。我可能会应用的重构操作是为您正在处理的每个不同数据集提取验证器类,在每种情况下与数据库交互的模型类,以及将三者绑定在一起的命令:接受数据,通过验证器传递数据,然后与各自的模型交互以持久化数据。然后,模型将根据成功的操作生成更改条目


如果您现在不愿意进行如此重大的更改,那么最好的第一步是将编辑函数中的不同部分分离到其他分区更好的函数中,并且在克服第一个障碍后只担心类和多态性。为了更好地理解代码被破坏的原因以及可以做些什么来修复它,我建议阅读一些类似重构(Martin Fowler)或实用程序员的文章。

只是一个想法,但是您可能希望有一种钩子系统来解决这个问题,而不是switch语句

所以,对于一个可能的东西清单,比如

item1, item2, ..., itemN
你可以试试类似的东西

function item1action ( ) { /* ... */ }
function item2action ( ) { /* ... */ }
function itemNaction ( ) { /* ... */ }
还有一些默认的方法,比如

function itemDefaultAction ( ) { /* ... */ }
因此,对于前面的switch语句,您可以改为

$function = "{$item}action";
if (! function_exists($function)) {
    return itemDefaultAction();
}
call_user_func($function);
return call_user_func($function)

我们能不能得到更多的信息,看看它在每个领域有什么不同的做法?你问的是一个特定的模式,但问题模糊不清。为什么不带一个真实的案例,而不是这些“东西”“不同的东西”之类的东西呢?对于一个每个项目都有一个功能的表(如Matt的“状态机”建议),什么是非未来证据?对于函数作为值的语言(如PHP),这是一种非常常见的“设计模式”。应该注意的是,在真实状态机中,每个函数都将返回下一个状态或下一个要运行的函数。具有讽刺意味的是,我见过使用switch语句实现的状态机。您的示例本身并不是一个真正的状态机,而是上面给定示例的有效替代方案。状态机可以很容易地实现为switch-case语句、函数、对象或任何适合您和您的项目的东西。它不仅会更清晰,而且执行速度也会更快,因为它将是一个符号查找,而不是条件检查。我想我会走这条路,因为这还没有投入生产,我可以在几个小时内修复它。在为时已晚之前征求意见。谢谢,我明白你的意思,这是为了测试数据库和粘贴可视化模板。在开始生产代码之前,我需要社区的意见。验证部分将被完全删除,这意味着它不会被硬编码到其中。谢谢