从四人帮中的FlyWeight
模式章节来看,当大多数对象状态可以变为外在状态时,FlyWeight模式是适用的。
外在状态
是什么意思?我感觉这个模式用于对象共享。如果对象要共享,那么它怎么可能有任何状态呢?
从四人帮中的FlyWeight
模式章节来看,当大多数对象状态可以变为外在状态时,FlyWeight模式是适用的。
外在状态
是什么意思?我感觉这个模式用于对象共享。如果对象要共享,那么它怎么可能有任何状态呢?
让我们以文字处理器为例:
文字处理器处理字符对象。字符对象的状态是字符内容、字体、样式、位置等(就文字处理器而言)。不同的文档使用字符的不同实例。假设我们只处理 a-z 字符,不同的文档使用来自 a-z 字母池中的字母,但可能应用不同的字体/样式。因此,如果我们将字符的内容与字体/样式分开,就可以共享这些字符,这是有意义的,因为不同类型的字符总数较少(在我们的案例中为26个,否则为一个常数),而不同文档中使用的字符实例却不同。共享这些字符实例意味着根据内容共享字符实例,并对这些字符外部应用上下文,如字体/样式。字符内容是内在状态,而字体/样式是外在状态。将状态分离为内在状态和外在状态导致了上述示例中大量的存储节省。
外在状态 - 指属于对象上下文(外部)或仅适用于该实例的状态。
内在状态 - 指自然属于 'FlyWeight' 对象的状态,因此应该是永久或不可变的(内部)或与上下文无关。
java.util.regex.Pattern
,即Flyweight,与使用它并保存本地外在状态的客户端对象Matcher
。许多Matcher
可以并行存在,所有的对象都在内部重复使用编译后的正则表达式。共享的flyweight越多,存储节约就越大。随着共享状态的增加,节约也会增加。当对象使用大量内在和外在状态,并且外在状态可以计算而不是存储时,节约最大。然后,您通过两种方式节省存储空间:共享减少了内在状态的成本,而将外在状态交换为计算时间。
Gang of Four的轻量级设计模式引入了“内在状态”和“外在状态”的概念:
换句话说,一个对象的状态可以被分解为内在状态和外在状态,其中内在状态是一组对象的所有状态的交集,而外在状态则是对象状态与内在状态的差异。由于内在状态在组中的每个对象中都重复出现,因此可以通过用单个存储单个内在状态的轻量级对象替换对象组来节省空间。然而,轻量级对象无法存储组中对象的多个外在状态,因此外在状态存储在外部,并在每个客户端对象的请求中传递给轻量级对象。这种优化的通信协议通常被称为无状态协议,因为轻量级对象不存储外在状态。无状态协议的示例包括IP和HTTP(更一般地,任何REST协议,其中内在状态称为资源状态,外在状态称为应用程序状态)。关键概念在于“内在状态”和“外在状态”的区分。内在状态存储在享元中;它由与享元无关的信息组成,因此可以共享。外在状态取决于并随享元的上下文而变化,因此不能共享。客户对象负责在需要时向享元传递外在状态。
o1 ← c1
o2 ← c2
o3 ← c3
我们可以将每个对象的状态分解为相对于这三个对象:
state 1 = 内在状态 ∪ 外在状态 1
state 2 = 内在状态 ∪ 外在状态 2
state 3 = 内在状态 ∪ 外在状态 3其中:
内在状态 = state 1 ∩ state 2 ∩ state 3
外在状态 1 = state 1 \ 内在状态
外在状态 2 = state 2 \ 内在状态
外在状态 3 = state 3 \ 内在状态
这里的内在状态是重复的。因此将其存储在单个享元对象中(并将外在状态移动到客户端)可以节省空间:
o ← c1, c2, c3