Java设计模式之singleton单例设计模式

现在网上到处是单例设计模式,都开玩笑说现在满城尽是singleton,呵呵,我也拿出来了,因为我平时用到最多的就是单例设计模式吧,而且比较简单,可以作为Java设计模式的入门篇吧。

SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个 人,那就是我(刚才做了个梦啦,哪有这么好的事)

单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的 “单一实例”的需求时才可使用。’‘————————–先引用下“从追MM谈Java的23种设计模式”文章中的说法。

单例设计模式形式有4种,一般人只知道有两种,懒汉式和饿汉式。
懒汉式(只有需要的时候才new出来,这里要用synchronized方法或代码块同步,因为在多线程情况下,不同的人同时进来拿到的引用可能都是null,结果都去new了)
public class LazzSingleton{
private LazzSingleton lazzSingleton = null;
 private LazzSingleton() {}//私有构造期 这个很重要啦,如果共有那么外面就可以随便new了,那么我们写这个单例意义就不大了,我发现公司老员工都写public的了,大家要注意下!

public synchronized LazzSingleton getInstance(){
 if(lazzSingleton==null){
   lazzSingleton = new LazzSingleton ();
return lazzSingleton ;
}
return null;
}

}

用的时候就:LazzSingleton lazzSingleton = LazzSingleton.getInstance();

饿汉式(一来就new,拿的时候直接拿对象)
public class HungerSingleton{
private HungerSingleton hungerSingleton = new HungerSingleton ();
private HungerSingleton() {}//私有构造期
public HungerSingleton getInstance(){
return hungerSingleton ;
}
}

用的时候就:HungerSingleton singleton = HungerSingleton.getInstance();

还有一种和饿汉式差不多(Effective Java这本书中有),因为式静态常量,当然内存中只有一个对象啦。
public class StaticFinalSingleton(){
public static final StaticFinalSingleton singleton= new StaticFinalSingleton();

private StaticFinalSingleton (){};//私有构造期
}

用的时候就:StaticFinalSingleton staticFinalSingleton = StaticFinalSingleton.staticFinalSingleton ;

最后一种我记不起来了,用的不多。(我有个坏习惯,嗯,比喜欢记笔记,而且记性不好,希望大家不要学我)

所以实现单例要点:1.私有化构造器(外部不能new),2.用对象名去引用属性(第三种)或静态方法(第一第二种);

应用场景(单例设计模式一般和工厂设计模式联合起来用,等做factory工厂模式时再一起使用,很简单)
如果你的系统中有要读配置文件,那么读配置文件的类就可以用单例设计模式了。例子:
public class LoadProperties {
 private static LoadProperties loadProperties = new LoadProperties();
 private LoadProperties(){};
 
 public static LoadPropertiesgetInstance(){
  return loadProperties
 }
 /**
  * 根据文件名、模块名,从配置文件中取得菜单名
  * @param model
  * @param fileName
  * @return
  */
 public String[] getMenus(String model,String fileName){
  //….
  return null;
 }
 /**
  * 根据文件名,读取显示风格
  * @param fileName
  * @return
  */
 public String[] getStyle(String fileName){
  //……
  return null;
 }

 }
 /**
  * 根据文件名,用户名,读取用户权限,<p>先判断用户级别,然后读取其权限</p>
  * @param fileName
  * @param user
  */

public String[] getPrivileges(String filename,String username){

    return null;

}

//……
}

接下来我们来做个实验,检验到底是不是singleton单例,单线程下我们一眼就看的出来是,所以我们就在多线程下测试。
package org.javaer.code.pattern;

public class Singleton {
 static LazzSingleton lazzSingleton1, lazzSingleton2;
 static HungerSingleton hungerSingleton1, hungerSingleton2;
 static StaticFinalSingleton staticFinalSingleton1, staticFinalSingleton2;

 public static void main(String[] args) {

  while (1 > 0) {
   new Runnable() {
    public void run() {
     lazzSingleton1 = LazzSingleton.getInstance();
     hungerSingleton1 = HungerSingleton.getInstance();
     staticFinalSingleton1 = StaticFinalSingleton.staticFinalSingleton;
    }
   }.run();

   new Runnable() {
    public void run() {
     lazzSingleton2 = LazzSingleton.getInstance();
     hungerSingleton2 = HungerSingleton.getInstance();
     staticFinalSingleton2 = StaticFinalSingleton.staticFinalSingleton;
    }
   }.run();
   System.out.println(lazzSingleton1 == lazzSingleton2 ? “是单例”
     : “不是单例”);
   System.out.println(hungerSingleton1 == hungerSingleton2 ? “是单例”
     : “不是单例”);
   System.out
     .println(staticFinalSingleton1 == staticFinalSingleton2 ? “是单例”
       : “不是单例”);
  }
 }
}

class LazzSingleton {
 private static LazzSingleton lazzSingleton = null;
 private LazzSingleton() {}
 public synchronized static LazzSingleton getInstance() {
  if (lazzSingleton == null) {
   lazzSingleton = new LazzSingleton();//需要的时候new出来
   return lazzSingleton;
  }
  return null;
 }

}

用的时候就:LazzSingleton lazzSingleton = LazzSingleton.getInstance();

class HungerSingleton {
 private static HungerSingleton hungerSingleton = new HungerSingleton();//先new出来
 private HungerSingleton() {}
 public static HungerSingleton getInstance() {
  return hungerSingleton;
 }
}

用的时候就:HungerSingleton singleton = HungerSingleton.getInstance();

class StaticFinalSingleton {
 public static final StaticFinalSingleton staticFinalSingleton = new StaticFinalSingleton();

private StaticFinalSingleton (){};
}

我们比较的是他们的内存地址,显示的结果一直是”是单例”,说明我们写的代码都是正确的单例设计模式。我这里人品比较好啊,用的Thread 和 Runnable实现多线程测试结果都一样,
我之前做过测试发现只有是Rnnable实现的多线程始终是”是单例”,而用Thread实现的多线程有的情况是,有的情况不是。我不是很清楚,貌似这是Rnnable 和Thread实现多线程有区别吧。
我弄了很久也不是很清楚,得看类的源码了,我们就不用关心啦,感兴趣的盆友就去研究下。

总结下:如果你的系统中需要的对象只有一个(为了节约内存,内存对于程序来说是非常重要的,尤其是嵌入式开发。不要以为你的内存大,用户访问多了,服务器的几十的G的内存也受不了,性能下降),如读取配置信息的类(多了去),不同的模块访问的公共类等等;那么就可以用单例设计模式了。Servlet的设计就是单例的,所有的用户拿到的都是服务器上的一个实例对象。(文/linmei.dong)转载请注明出处http://mtoou.info/java-singleton/

发表评论

邮箱地址不会被公开。 必填项已用*标注