子墨对酒《三国杀》里论模式(肆)单例模式

当设计模式的观点被众人所推崇的时候,单例模式似乎已经成了掌握设计模式时候要掌握的基础模式。当然我并不认为设计模式中有基础和非基础之分,我只觉得模式的应用有普遍和非普遍之别。单例模式的普遍并不体现在应用场景多上,我们阅读一个项目的时候发现其实用到单例的类本身屈指可数。但是因为它写法简单,易于识别,所以我们才对它格外的注意。单例模式分成饿汉式和懒汉式。这两种模式在写法上有一定的区别,你不能单独地推崇某种写法。这些都是要根据具体的场景来区分。现实中单例的场景屡见不鲜,windows系统中的回收站就是典型的单例场景。在windows系统中,回收站是只会存在一个的东西。其实从结构来说,操作系统也是一个单例,部署在操作系统之上的所有进程都共享同一个系统,只不过是被映射到自己的虚拟空间中去。现实中,对于一个国家的zhuxi,总统,家庭里的一家之主从概念上都可以称其为单例。是的,单例模式的名字非常的应景,就是单个的实例。当然也有一些书籍上面写到单件模式,我们知道是一个东西就行。

单例模式的懒汉式写法是一种lazy load的写法

class Instance {

     public static Instance getInstance() {

       if (sInstance == null)  new ;...

  }

}

这里我们可以看出采用懒汉式写法出现的一些问题,最直观的就是线程同步。为了保证线程同步我们可能采用:

     public sync static Instance getInstance() {

       if (sInstance == null) ...
  }

增加syn关键字的方式来同步数据。但是我们知道,线程同步会严重的降低代码运行的效率,如果你打算使用同步的话,不妨可以考虑降低代码块的大小:

  public  static Instance getInstance() {

         sync(lock) {

         if (sInstance == null) new;

        }

        ...
  }

那么这就满足了么?我们当然不会满足现状,我们如果还想要跟深层次的优化,我们不妨考虑的更底层一点。我们假设底层的cpu或者运行虚拟机采用的是流水线方式处理指令,那么如果你的假设条件为真的可能性比较大的时候,那么流水线建立成功的可能性就大。我们知道sInstance这个对象==null只有在第一次被调用的时候,既然这样,sInstance==null这个条件出现的概率几乎为0.因此为了保证流水线的稳定我们将条件换一种写法:

public  static Instance getInstance() {

         sync(lock) {

         if (sInstance != null) return;

        }

        ...
  }

当然这种方法可能在宏观上的效果并不明显,虚拟机或者CPU也未必按照我们的方式来运行,但是我还是推崇这种习惯。那有没有一种不使用同步块,又能避免同步问题的,而且也不用主动的new单例的写法呢?~

当然是有的,首先我们要建立一个知识点,就是java中的类加载是一种lazy load的机制。每一个类只有在使用的时候才会被加载,加载的过程本身就是同步的。

public  static Instance getInstance() {

               return Inner.INSTANCE;
  }

static class Inner{

    public static final Instance INSTANCE;

}

代码中我们用到了内部类的方式来获得单例数据。这就完成了同步和lazyload单例的功能。

饿汉式的写法就简单的:

class Instance {

    private static final Instance INSTANCE = new ...

}

我们发现单例在Instance类被加载的时候就产生,至于有没有必要要final这个参数其实无所谓,我偏爱加上,主要为了增加一点微不足道的效率。

我们来看看三国杀。《三国杀》里的消息盒子就是一个比较单例。


我们不妨设想一下如果采用两个对象来存储消息的话,那么消息的同步就是一个非常懊恼的问题之一。你可能在任何模式下接受消息,也有可能在任何模式下修改消息,或者删除消息。对于单例对象来说一个对象改变了那么你整个的程序中部署在这个对象上的观察者就会变化。另外单例模式也是我们前文提到的IOC的一种表现。关于IOC的信息请参考:

http://blog.csdn.net/hello__zero/article/details/18815487

                                                                                                                                         --非子墨

微博账号: 非子墨
QQ:1025250620
CSDN:《非子墨》的空间

猜你喜欢

转载自1025250620.iteye.com/blog/2015108