了解工厂设计模式

时间:2013-01-30 14:52:19

标签: php design-patterns

我正在学习php中的工厂设计模式。据我所知,这种模式在我们有一堆类的情况下很有用,比方说, class_1,class_2,class_3 等。 如果必须实例化的特定类只在运行时知道,那么我们不是使用new运算符为这些类创建对象,而是创建一个工厂类,它将为我们完成工作。

工厂类看起来有点像这样:

class Factory
{
// $type will have values 1, 2, 3 etc.
public function create_obj($type)
{
  $class_name = "class_".$type;
  if(class_exists($class_name))
  {
        return new $class_name();
  } 
}
}

我的问题是在这里使用工厂的优势是什么?为什么不使用简单函数而不是一个会使事情变得复杂的类?

4 个答案:

答案 0 :(得分:2)

您的代码段中的方法不是工厂方法,而只是一个执行众所周知的reflective任务的辅助方法:根据其名称实例化一个类。这与Factory pattern的目的完全相反:创建对象(产品)而不指定将要创建的对象的确切类

如维基百科中所述:

  

此模式的本质是“定义用于创建对象的接口,但让实现接口的类决定实例化哪个类。”

您可能对PHP example中的最后Wikipedia article on Factory pattern感到困惑,是的,这是一个不好的例子。检查上面的Java example是否有一个有意义的例子(试图将其转换为PHP的人错过了整点)。 Java示例根据其扩展名返回文件读取器,这正是工厂模式的用例。创建自己的个人“规则”,某些类需要具有特定的名称前缀,这很可能是一个糟糕的设计决策。

答案 1 :(得分:1)

在问题的基础上,你可以使用一个简单的函数来实现目标。如果这种情况发生故障,那就是程序员最佳实践,你需要低耦合,高内聚。

该功能本身在您的应用程序设计中起着特殊的作用,并将其与具有不同角色和用途的其他功能放在一起,对于维护和阅读来说是不直观的。请记住,模式用于简化(几乎)普遍通过项目域面临的常见问题,因此它们倾向于从代码库的其余部分进行细分,以帮助区分它们。

此外,通过将模式放在自己的类中,任何需要使用它的类都不需要知道class_1 / 2/3 / etc的类结构。而只需要引用父类,允许您在线下创建更多类,相应地修改模式,而无需解析剩余代码中的依赖项和链接。这与低耦合有关。

答案 2 :(得分:1)

这个概念是你设计一个接口,然后你可以稍后换掉这个类。

暂时忘记这种模式,考虑一下:

if (type == "manager")
    employee = new manager();
else
    employee = new employee();

employee.name = "myname";

在这种情况下,员工和经理都从同一个类继承。在if语句之后,您可以像对待人一样对待它们,并且您从实际实现中抽象出来。您可以实现工厂模式,而不是遍布整个地方的if语句。如果你只有一对,这种模式可能有点过分。如果您希望将来轻松扩展该程序,请考虑一种模式。

答案 3 :(得分:1)

使用工厂模式的另一个重要原因是,当您必须为您的设计添加类时,请考虑代码会发生什么。代码。
如果您没有使用工厂模式,您的代码将越来越<强>紧密耦合,
您必须在许多不同的地方进行更改。您必须确保您必须触摸代码的每个地方都与您必须触摸的所有其他(紧密耦合)地点相协调。 测试变得更复杂,更复杂,并且有些事情会破裂。

Factory Pattern为您提供了一种减少耦合的方法,并帮助您将职责封装到几个地方。使用工厂模式,添加其他类意味着在更少的位置触摸代码。简化了测试(构建测试用例以及运行测试)。

在现实世界中,大多数代码都很复杂,足以使工厂模式的好处变得清晰。改变,改进和发展对象模型,使面对快速变化的测试尽可能完整和严谨,并确保您尽可能地使代码变得非常严格(同时意识到多个人将会成为在几个月/几年的时间里进行工作) - 工厂模式通常是不费脑子的。

通过一个简单的例子,很难看出使用工厂模式的优势。 (如果你的代码真的很微不足道,那么这种模式可能不会给你带来太大的帮助。)这是我在网上搜索时看到的很多例子的问题 - 这些例子往往集中于'你可以确定在运行时上课!'并且过于简单化。

这是一个不太琐碎的例子,我认为让人们想到这个模式的所有可能的好处:  A presentation on the Factory Pattern by Bob Tarr (pdf)。 (这是例子2,从第10页开始。)想象一下,你正在写一个迷宫游戏,一个人必须探索迷宫和迷宫中的所有房间。您的对象模型包含迷宫,其中包含会员墙> 等内容,并且 >地图,还必须跟踪它们。很简单。但是当你开始添加魔法房间魔法门魔术窗会说话的图片时会发生什么Twisty Little Passages ?你最终将会有很多课程代表一切;您希望确保在添加新类时必须尽可能少地更改(触摸)代码。并且您不希望必须修改 Map 类中的代码,例如,每次添加新类时:您希望将类重点放在它们应该负责的内容上

不仅要考虑在运行时实例化的内容,还要考虑代码复杂性 他还给出了一个使用工厂模式(具体为工厂方法)和UI组件的示例 - 其中工厂模式出现了很多。 (对于初学者,或者从未处理过UI代码的人,我认为这个例子并不那么明确。)

请记住,大多数编码都是在现有代码上完成的:大部分时间用于修改已存在的代码。您希望确保您的代码能够处理更改而不会变得脆弱。减少耦合和封装责任将大大有助于实现这一目标。

相关问题