懒初始化
原文: LazyInitialization 设计 Bliki 索引
一个变量(在OO语境中常为class的一个字段)第一次存取时才被初始化,这项技术叫做懒初始化,其常规形式如下(C#):
public FooClass Foo {
get {
if (_foo = null) _foo = calculateFoo();
return _foo;
}
}
若得到某个字段值的计算过程很耗时,你想推迟至真正用到它时再计算,这时适宜采用懒初始化。也就是说,这个字段很多情况下用不到,或我们为了迅速初始化这个object宁愿把耗时的事往后拖,懒初始化通常很适合处理这些情况。
需要记住这是一项优化技术,一些值客户端当即并不需要,它们被懒初始化,这种优化提高了响应性。与其他优化技术一样,应到确实需要解决性能问题时再采用。
尤其是这项技术还可能导致调试上的麻烦。比如在调试过程中,你查看一个懒初始化字段,它被赋值的那一刻也就意味着系统发生了一个状态改变(尽管 可见状态没变,但实际状态变了),而这在正常情况下(不需此字段时)并不发生,因此当你加上个调试打印语句时,bug们好像无影无踪,一直藏到周五下午才发难——记住我传授你的这个捉虫秘方噢
。
可见状态
原文: ObservableState 设计 Bliki 索引
人们说一个方法不修改一个object的可见状态,这是什么意思呢?
把修改状态的方法和不修改的分开,这么做很有用。不修改状态的方法(我称之为query)可以在任何上下文中调用,无需像别的方法那样担心它们的调用顺序。
这里的关键点并不是它们什么状态都不修改,而是不修改可见状态。一个object的可见状态是那些通过query方法可以得到的状态——还是看一个快捷的例子吧。
最简单例子是缓存(cache),看下边这个表示区间的class:
# ruby
class MyRange
attr_reader :start, :finish
def initialize start, finish
@start, @finish = start, finish
@lengthCache = nil
end
def length
@lengthCache = (@finish - @start) unless @lengthCache
return @lengthCache
end
end
我们有一个变量lengthCache,应用 懒初始化技术,第一访问时被填充。给lengthCache赋值显然对这个object的实际状态做了修改,但它的可见状态并没改变,因为你从外面看不到这个object的状态变了。
我说“从外面看不到”意思是,不管lengthCache的值已经被填充了还是没被填充,这个MyRange object的任何方法被别的object调用所得到的结果都一样。
实现MyRange其他方法时,所有用到区间长度的地方都不直接读lengthCache字段,而是调用length方法获得——这是达到上述效果的典型做法。缓存的改变不应该是可见的,这是个明显的例子。另外一点是,所有懒初始化过程都不应修改可见状态。
原文: LazyInitialization 设计 Bliki 索引
一个变量(在OO语境中常为class的一个字段)第一次存取时才被初始化,这项技术叫做懒初始化,其常规形式如下(C#):
public FooClass Foo {
get {
if (_foo = null) _foo = calculateFoo();
return _foo;
}
}
若得到某个字段值的计算过程很耗时,你想推迟至真正用到它时再计算,这时适宜采用懒初始化。也就是说,这个字段很多情况下用不到,或我们为了迅速初始化这个object宁愿把耗时的事往后拖,懒初始化通常很适合处理这些情况。
需要记住这是一项优化技术,一些值客户端当即并不需要,它们被懒初始化,这种优化提高了响应性。与其他优化技术一样,应到确实需要解决性能问题时再采用。
尤其是这项技术还可能导致调试上的麻烦。比如在调试过程中,你查看一个懒初始化字段,它被赋值的那一刻也就意味着系统发生了一个状态改变(尽管 可见状态没变,但实际状态变了),而这在正常情况下(不需此字段时)并不发生,因此当你加上个调试打印语句时,bug们好像无影无踪,一直藏到周五下午才发难——记住我传授你的这个捉虫秘方噢
![](https://p-blog.csdn.net/images/p_blog_csdn_net/mfowler/icon_smile.gif)
可见状态
原文: ObservableState 设计 Bliki 索引
人们说一个方法不修改一个object的可见状态,这是什么意思呢?
把修改状态的方法和不修改的分开,这么做很有用。不修改状态的方法(我称之为query)可以在任何上下文中调用,无需像别的方法那样担心它们的调用顺序。
这里的关键点并不是它们什么状态都不修改,而是不修改可见状态。一个object的可见状态是那些通过query方法可以得到的状态——还是看一个快捷的例子吧。
最简单例子是缓存(cache),看下边这个表示区间的class:
# ruby
class MyRange
attr_reader :start, :finish
def initialize start, finish
@start, @finish = start, finish
@lengthCache = nil
end
def length
@lengthCache = (@finish - @start) unless @lengthCache
return @lengthCache
end
end
我们有一个变量lengthCache,应用 懒初始化技术,第一访问时被填充。给lengthCache赋值显然对这个object的实际状态做了修改,但它的可见状态并没改变,因为你从外面看不到这个object的状态变了。
我说“从外面看不到”意思是,不管lengthCache的值已经被填充了还是没被填充,这个MyRange object的任何方法被别的object调用所得到的结果都一样。
实现MyRange其他方法时,所有用到区间长度的地方都不直接读lengthCache字段,而是调用length方法获得——这是达到上述效果的典型做法。缓存的改变不应该是可见的,这是个明显的例子。另外一点是,所有懒初始化过程都不应修改可见状态。