概念
一个对象,它虽然不包含所需要的所有数据,但是知道怎么获取这些数据。
加载一个对象会引起大量相关对象的加载,这样会损害系统的性能。延迟加载会暂时终止这个加载过程。
运行机制
四种实现延迟加载的方法:
- 延迟初始化(Lazy initialization)。每次访问属性域都要先检查该域是否为空,如果为空,计算并返回这个域值。适用于活动记录、表数据入口和行数据入口模式。
- 虚代理(virtual proxy)。既然是延迟加载,必然需要一个附加的间接层,虚代理是一个虚对象,只有当其中一个方法被调用时,才从数据库加载适当的对象。
- 值保持器(value holder)。用来包装某个其他对象的对象,只有第一次访问值保持器时它真正从数据库读取数据。缺点:类需要知道它的存在。
- 重影(ghost)。是部分状态下的真实对象。当从数据库加载对象时,只包含ID,每次要访问某个域时,会加载其完全状态。
一些讨论
延迟加载适合于面向方面的程序设计,置于一个单独的方面,可以独立改变延迟加载策略。
为不同的用例配备不同的延迟加载策略,往往能够使二者配合的很好。例如,如果使用数据映射器,就可以需要两个订单映射器对象,一个直接加载订单项,另一个对象延迟加载这些项。
使用相同的基本加载方法,使用不同的策略对象决定加载模式。
使用时机
- 只有在域需要另外的数据库访问时才考虑使用延迟加载,对数据库同一记录的剩余部分实施延迟加载意义不大,即使其余部分的数据域很大。
- 从性能角度看,实施延迟加载取决于什么时候想取回数据。对应同一个用户界面的一次交互时,一次取回所有数据最为理想。
- 需要额外的调用,并且当使用主对象时,所调用的数据还没有用到的时候。
- 使用延迟加载增加了编程的复杂程度,因此需要时才使用延迟加载。
示例-延迟初始化(java)
示例-虚代理(java)
示例目标:仅仅当供应商中的产品列表被首次访问时才生成一个产品list
实现思想:在数据映射器中先将延迟机制做预处理,为将来获取域list做准备
Step1 建立供应商虚列表类
Step2 需要一种机制,使得当虚列表实例化时,调用具体的生成列表代码(具体的产品列表加载方法)。
Step3 建立虚列表类
Step4映射器通过实例化具体的加载方法而不是虚加载方法,建立域列表
说明:setProducts方法的参数并不是List类型,虽不能直接使用,但可以由VirtualList类型中的方法返回,即VirtualList::source
总结:领域类不关心映射器如何进行延迟加载,延迟加载完全由虚代理自行维护。领域类通过虚代理建立域数据的触发时机是:虚代理中的getSource方法,进而触发ProductLoader中具体的load()方法。
示例-值保持器(java)
示例说明:和虚代理模式相似,区别在于域list直接保存在值保持器中,List对象则由值保持器提供的方法返回,而虚代理保存在List类型依靠虚代理返回。
Step1 建立供应商值保持器类
Step2 需要一种机制,当访问值保持器时,需要向其传递相应代码。
Step3 映射器通过实例化具体的加载方法而不是虚加载方法,建立值保持器
说明:值保持器可以作为通用的延迟加载使用。
示例-使用重影(C#)
领域对象需要相应的映射器,为了避免直接调用依赖,需要合并注册表和分离接口
重影的加载序列:
标签:Load,Lazy,映射器,对象,示例,加载,设计模式,方法,延迟 From: https://blog.csdn.net/workflower/article/details/141131600