设计模式之旅(1)——单态模式,独生子女的IT生活

作者:马靖
联系方式:andamajing@163.com
版权声明:欢迎大家转载,转载请标明出处,尊重原创,从你我做起。
备注:自2014年1月14日起,本人上传的经典书籍,将不再收取资源分,欢迎大家下载学习,好东西一起分享,共同建造良好的网上学习环境。

让我们从一段对话开始我们今天所讲的话题。

老公:老婆,你们家就你一个吗?

老婆:找打啊你,我们家我有没有兄弟姐妹你都不知道啊,晚上跪键盘去,除了我,还有两个姐姐,两个哥哥,还有个宝贝弟弟呢。

老公:哇,那么多啊,那岂不是小时候在一起玩疯了你们,肯定小时候你没少调皮让你爸妈省心。

老婆:对的呢,不过像你这样家里只有一个独生子的,小时候多没劲啊,孤独寂寞吧哈哈。

老公:虽然没人玩,但是家里的玩具都归我管,想吃什么就吃什么,没人跟我抢,所以只有一个独生子也是不错的呢嘿嘿。

.............

闲话不多说,从上面的对话我们知道,家里只有一个孩子也是有其好处的嘛,在软件设计中,我们有时也会需要将某个对象只生成一个,因为太多可能会造成混乱,不利于管理,例如我们的Windows任务管理器,Java类加载器,注册表等,都是指有一个,那么该怎么设计实现呢?这就是本人需要讲述的问题。

为了解决上面的问题,单态模式应运而生,作为设计模式中最简单的设计模式,我想今天我们就首先来看看它到底是什么?

首先,我问大家一个问题,如果让你设计一个类,这个类只能生成一个对象,大家会怎么设计呢?想想先.......

肯定不能有公有的构造函数,否则外部就可以通过new操作创建出很多对象,于是我们想到把类的构造函数设置为private权限,新的问题又来了,既然是private,那么如何去创建对象呢?既然我们无法通过new创建得到,那么我们就只有通过类的静态方法来获得这个对象了,当然我们需要在类中定义一个该类对象的引用,而且这个引用应该是私有的静态的。如下所示:

public class Singleton
{
private static Singleton instance=null;
private Singleton(){}
public static  Singleton getInstance()
{
if(instance==null) instance=new Singleton();
               return instance;
}
}


其结构图如下所示:

设计模式之旅(1)——单态模式,独生子女的IT生活

这就是单态模式的一个简单实现(当然这种写法还是有点不足的,在后满我们将进行详细讲述),我们可以看到,单态模式中包含三个主要部分,一个是私有的对象,私有的构造函数,和公有的静态获取函数(用于得到对象的引用)。设计模式之旅(1)——单态模式,独生子女的IT生活

这里我们给出单态模式的定义:单态模式确保每个类只有一个实例,并且提供为这个私有对象提供一个全局的访问点。

刚才提到了上面的程序实际上是有问题的,现在我们就来讨论一下。

你是否学习过多线程编程?如果没有学过,那么先看看这个多线程的资料吧或者你应该听说过这个吧,在多线程编程模式下,上面实现的单态模式是有问题的,请看下图:

设计模式之旅(1)——单态模式,独生子女的IT生活

所以,我们需要对上述代码进行改进。下面给出三种解决办法,大家可以根据自己的情况和实际项目的要求进行选择使用。

(1)对共有的外部进口进行同步化。即将方法用synchronized关键字修饰,如下所示:

public static synchronized Singleton getInstance()
{
if(instance==null){instance=new Singleton();
return instance;
}


这样,当一个线程进入方法以后,其他线程只有等到该线程退出该方法才能进入。由于在每次调用该方法时,都会进行同步处理,对程序执行效率有一定影响,一般同步一个方法可能会造成程序执行效率下降100倍,所以,如果使用比较频繁,请不要使用该方法。

(2)采用在类加载时直接创建对象,如下所示:

public class Singleton
{
private static Singleton instance=new Singleton();
private Singleton(){}
public static synchronized Singleton getInstance()
{
return instance;
}
}


这种方法使得JVM在加载这个类时会创建唯一的对象,并在以后访问该对象时指向的都是同一个。这种方法的缺点在于,如果这个类的初始化需要做大量的工作,而后这个类在之后并没有被调用,则会造成较大的资源浪费。

(3)使用双重检测加锁,如下所示:

public class Singleton
{
private voilatile static Singleton instance=null;
private Singleton(){}
public static synchronized Singleton getInstance()
{
if(instance==null)
{
synchronized(Singleton.class)
{
if(instance==null)
{
instance=new Singleton();
}
}
} 
return instance;
}


使用该方法,首先检查该实例是否已经创建好,如果未创建,才能同步,这样一来,只会在第一次创建的时候可能出现同步,降低了同步造成的性能损失。

到此为止我们对单态模式有了详细的认识了。设计模式之旅(1)——单态模式,独生子女的IT生活






设计模式之旅(1)——单态模式,独生子女的IT生活

上一篇:Hibernate的相关问题


下一篇:高性能消息系统——Kafka