本文首发于 http://www.YoungZY.com/
意图
- 通过共享来高效地使用大量的细粒度的对象
- 用轻量级组件代替重量级组件
问题
对象设计粒度越细越能提供更好的灵活性,但就性能和内存的使用而言,代价可能高得令人无法接受。
讨论
蝇量设计模式描述了如何在合适的粒度上共享对象并且避免过高的开销。每一个”蝇量”对象被分成两个部分:状态依赖的(外在的)部分和非状态依赖的(内在的)部分。内在的状态(共享的)被存储在蝇量对象里。外在的状态被客户端对象存储或计算,在调用蝇量对象时传递给它。
Motif组件就是一个例证,它已被重新设计为轻量级的组件。各组件已经足够的“智能”而独立,各组件与它们所在的布局管理组件有一种依赖关系。每一个布局管理器提供了上下文相关的事件处理机制、资源管理和服务给蝇量组件,而每一个蝇量组件只有跟上下文无关的状态和行为。
结构
蝇量对象存储在工厂的仓库中。客户端克制自己不直接创建蝇量,而是从工厂获取。蝇量对象不能孤立地存在。任何可能导致不能共享的属性必须由客户端在调用蝇量对象时提供。如果上下文有助于“规模经济”(即客户可以很容易地计算或查找所需的属性),则蝇量模式将提供合适的杠杆。
Ant
(蚂蚁)类,Locust
(蝗虫)类和 Cockroach
(蟑螂)类可以被轻量化是因为他们实例相关的状态被反封装或者外在化了,而且必须由客户端提供。
举例
现代浏览器使用这种技术来防止同样的图片被重复加载。当浏览器加载一个页面时,它遍历了页面上所有的图片。浏览器从网络上获取新的图片然后将他们放在缓存中。对已经加载过的图片,蝇量对象被创建了,它会有一些唯一的属性(如在页面中的位置),但其他的都指向了缓存数据。
核查清单(也可以理解为应用步骤)
- 确认当前的对象就是需要关注的问题,同时客户端能够并且愿意接受责任的转移。
- 将目标对象的状态分为可共享的(内在的)和不可共享的(外在的)。
- 将不可共享的状态从类属性中移除,把它作为调用方法的参数。
- 创建一个工厂用来缓存和重用已经存在的实例。
- 客户端必须使用这个工厂类而不是
new
获取对象。 - 客户端(或者第三方)必须找到或计算出不可共享的状态,然后在调用方法时提供这些状态。
经验法则
- 解释器抽象语法树中的终端符号可以通过蝇量实现共享
(译者注:详细的代码实例请移步 GitHub )
加入讨论