懒惰初始化

Slappy Joe’s burgers 是一家高品质餐厅,汉堡在制作完成后会根据所用肉类的精确重量进行定价。遗憾的是,由于制作时间较长,如果在顾客点餐前就制作好每一种汉堡,将会耗费大量资源。

与其将每种汉堡都准备好供顾客点餐,不如在顾客点餐时才制作汉堡(如果还没有的话),然后向顾客收取相应的费用。

Burger.php 类的结构如下:

Unresolved include directive in modules/ROOT/pages/ch03/ch3-05.adoc - include::example$/Chapter 3/LazyLoader/Burger.php[]

请注意,汉堡的价格只有在汉堡实例化后才会计算,也就是说,在汉堡制作完成之前,无法向顾客收取费用。类中的另一个函数只是返回汉堡的价格。

我们没有直接从 Burger 类中实例化,而是创建了一个名为 BurgerLazyLoader.php 的懒惰初始化类,该类存储了已制作好的每个汉堡的实例列表。另外,如果某个特定配置的汉堡已经存在,则会返回该汉堡。

这是根据需要实例化 Burger 对象的 LazyLoader 类:

Unresolved include directive in modules/ROOT/pages/ch03/ch3-05.adoc - include::example$/Chapter 3/LazyLoader/BurgerLazyLoader.php[]

添加的唯一其他函数是 getBurgerCount 函数,它返回 LazyLoader 拥有的实例中的所有实例的计数。

因此,让我们将所有这些内容一起包装在我们的 index.php 文件中:

Unresolved include directive in modules/ROOT/pages/ch03/ch3-05.adoc - include::example$Chapter 3/LazyLoader/index.php[]

然后我们得到这样的输出:

image 2023 10 27 18 42 40 707

由于价格是随机的,你会发现数字会有所不同,但第一次和最后一次调用时,芝士汉堡和薯条的价格是一样的。实例只创建一次;而且,它只在需要时创建,而不是想实例化时就实例化。

撇开假设的汉堡店不说,这种创建模式在需要时也有一些妙用,比如当你需要延迟从一个类中构造一个对象时。当构造函数是一项昂贵或耗时的操作时,通常会使用这种模式。

如果一个对象还没有被使用,那么就可以及时创建一个。