PHP-DI的get和make方法的区别

Using the container 章节提到过:

The make() method works like get() except it will resolve the entry every time it is called. Depending on the type of the entry this means:

  • if the entry is an object, an new instance will be created every time
  • if the entry is a factory, the factory will be called every time
  • if the entry is an alias, the alias will be resolved every time

翻译成人话就是:

make方法和get方法是相似的,但是make方法每次调用都会重新解析entry(即重新new创建对象,我的理解是它是为了执行构造方法而存在的),不同的情况会产生不同的效果:

  • 如果entry是个对象,则每次调用就会新建实例
  • 如果entry是个factory,则factory每次都会被调用
  • 如果entry是个别名,则别名每次都被重新解析

换言之,使用get会优先获取容器中已经实例化的对象,如果没有实例化就先实例化;而make则会每次都实例化。get代表单例模式,make代表工厂模式,大概就是这么理解。

文档还说:

Container::make() is useful for creating objects that should not be stored inside the container (i.e. that are not services, or that are not stateless), but that have dependencies. It is also useful if you want to override some parameters of an object's constructor.

翻译:Container::make() 是为了创建不储存在容器内部但有依赖关系的对象的(例如非服务或无状态对象)。当然,如果想覆盖掉一些构造方法的参数,这也十分有用。

这里介绍的是make方法的主要作用,正如我所说,它是为工厂模式而存在的,而且它也能实现替换掉一些构造方法的参数,实际上就是代替我们去new一个对象而已,这跟我们直接new一个对象其实并没有什么区别(当然,如果你在配置文件已经写好构造方法参数,这会省下一些代码)。工厂模式就是为了解放“重复劳动”而存在的,一些类的构造方法又长又臭,我们每次new都要写一大堆参数就很烦,make方法就是我们的“救星”。我觉得用过Laravel的小伙伴应该会有所了解。

上面的理解,是根据我使用PHPUnit进行测试验证得来的结果,跟我的猜想一致。实际上,文档确实已经描述了它们的区别,但没有提到“单例模式”和“工厂模式”,让我们无法立即理解。所以,凡事都需要动手验证,不能光靠吃透理论知识,不能迷信权威。要相信,自己动手做的才是真。

发表评论