【第2条】用私有构造函数强化singleton属性

    singleton即单例模式。【第1条】中我提到的Session性质的全局唯一实例既是单例模式。它只能被实例化一次,通常代表本质上具有唯一性质的东西。

 

除了Session的例子外,我这里还有一个很微妙的例子:

 

 new MessageBox("Hello World ! ").show();

 

 MessageBox.show(new MessageBox("Hello World ! ");

 

 MessageBox.show("Hello World ! ");

 

 MessageBox.getInstance().show("Hello World ! ");

 

    很显然第一个是多实例模式,每次new的时候都会构造一个新的MessageBox类(如果MessageBox是非可变类,可能并非每次都会构造新的,如果碰巧形参的字符串曾经出现过,就不必再构造新的实例了)。

 

    第二个使用一个静态方法(只是普通的静态方法)来显示消息框,但是作为传入的参数,还是一个刚刚被创建的MessageBox类。

 

    第三个和第二个比较类似,只是少了一层“脱了裤子放屁”的new,直接把String作为参数给show()。现在是单例模式了吗?答案是可能是。也可能不是,而“进一步”是不可实例化的工具类(util),参考【第3条】。

 

    第四个呢,从getInstance一眼就能看出,这不是【第1条】中刚刚讲到的静态工厂方法吗。OK,只要MessageBox的作者不是个糊涂的程序员,那么可以几乎可定它是一个单例模式。

 

    那么如何才能保证一个类只能被实例化一次呢?(也就是说怎么才能说刚才那个MessageBox的作者不是个糊涂的程序员呢?)实现的方法有2种:这2种的共性是

1)都把构造函数声明为私有的,别人无法通过调用构造函数来创建类的事例了。

2)都有一个静态的成员,用来保持(保存)这个“单实例”

 

不同点是:

方法1)将这个静态成员声明为公有的,供他人直接使用。

public class Example{

   public static final Example INSTANCE=new Example();

   private Example(){     //构造函数为私有
   ...}
   ....
}

 

方法2)将这个静态成员声明为私有的,通过静态工厂方法供他人使用。

public class Example{

   private static final Example INSTANCE=new Example();//改为私有

   private Example(){     //构造函数为私有
   ...}

   public static Example getInstance(){
      return INSTANCE;
    }   
....
}

 

 

    2种方法的优缺点其实并不大,由于第2种更为灵活,对将来的扩展也留有更多的余地,所以我个人还是更倾向于第2种。

 

 

    我在开发的Framework中,单实例的应用并不多(一个项目中如果太多反而是要思考了),其中一个最突出的应用就是UserSession,它记录了客户的登录信息,显然一个用户只能有一个UserSession。

 

    通常这样的类最好也是非可变的,见【第13条】。但是由于其他原因这里的UserSession无法做成非可变类,这个到【第13条】时再细说。

 

 

 

【Effective Java 学习笔记】系列连载专题请见:
http://tonylian.iteye.com/categories/64208

 

 

你可能感兴趣的:(【第2条】用私有构造函数强化singleton属性)