懒汉模式(lazy evalution)

来源:互联网 发布:匈奴 知乎 编辑:程序博客网 时间:2024/05/16 08:37

    之前学过设计模式中的单例模式,用Java代码(来自《深入浅出设计模式》)可以表示如下:

//饿汉式单例模式 public class Singleton{    private static Singleton uniqueInstance = new Singleton();    private Singleton(){}    public static Singleton getInstance(){        return uniqueInstance;    }}


//懒汉式单例模式 public class Singleton{    private volatile static Singleton uniqueInstance;    private Singleton(){}    public static Singleton getInstance(){        if(uniqueInstance == null){            synchronized(Singleton.class){                uniqueInstance = new Singleton();            }         }        return uniqueInstance;    }}

 

这样的问题,在面试中也是常考的题。它们有什么区别,大家看代码就可以很容易得知。

        最近,在看《More Effective C++》一书,上面条款17:考虑使用lazy evalution(缓式评估)。这里的lazy和上面的懒汉很相似。

        懒汉模式,关键在于拖延战术,像上面的代码,只有在用到uniqueInstance的时候才去实例化。因为实例化一个对象是很耗时间和空间的,尤其对于大对象来说。

在《More Effective C++》中,主要讲了4个用途。

1 Reference Counting(引用计数)

例如:

String s1 = “Hello”;

String s2 = s1;

缓式的做法是,让s1s2共享字符串“Hello”,只有当需要修改s1或者s1的时候才去创建s1的副本给s2

区分读和写

例如:

String s = “Homer’s Iliad”;//假设s是个reference-counted字符串

.......

cout << s3[3];

s[3] = ‘x’;

如果只是读取的话,我们可以继续使用前面的变量共享,所以我们要判断操作符[]是在读还是写的环境被调用。

缓式取出

       想象你的程序使用大型对象,其中包含很多字段。如果每次用到的话,都是把整个对象取出是不合适的做法,因为不一定每个字段都用到。缓式的做法是,我们只产生一个空的对象,当对象内的某个字段被需要了,程序才从数据库中取回对应的数据。

4 Lazy Expression Evaluation (表达式缓评估)

考虑下面的代码:

Template <class T>

Class Matrix {...};

Matrix<int> m1(1000, 1000);  //一个1000*1000的矩阵

Matrix<int> m2(1000, 1000); / /一个1000*1000的矩阵

...

Matrix<int> m3 = m1 + m2;

        这样的话,如果一上来就把m3的值全部计算好,也是不合适的,因为后面的代码不一定全部用到其中的每个元素。假如,后面的程序只要m3[4]呢,全部计算的结果岂不是浪费了。

        关于是否要用懒汉模式,取决于实际情况,只有当“你的软件被要求执行某些计算,而那些计算其实可以避免”的情况下,lazy evaluation 才有用处。

       另外,也是很重要的一点是,那些class 接口对于是否使用eager evaluationlazy evaluation 不能露出半点蛛丝马迹。

       记不清哪位大神曾经说过,大概的意思是:“硬件再快,也要考虑算法的效率”,这个主题正是体现了这个思想,尽管现实的硬件已经白菜价了。