Chinaunix首页 | 论坛 | 博客
  • 博客访问: 26311652
  • 博文数量: 2065
  • 博客积分: 10377
  • 博客等级: 上将
  • 技术积分: 21525
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-04 17:50
文章分类

全部博文(2065)

文章存档

2012年(2)

2011年(19)

2010年(1160)

2009年(969)

2008年(153)

分类: Java

2010-03-24 13:22:34

Java中的单例模式

单例模式是设计模式中使用很频繁的一种模式,在各种开源框架、应用系统中多有应用.像在ORM框架中就使用频繁。

一、定义与结构

单例模式又叫做单态模式或者单件模式。在GOF书中给出的定义为:保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式中的单例通常用来代表那些本质上具有唯一性的系统组件(或者叫做资源)。比如文件系统、资源管理器等等。

二、单例模式的目的就是要控制特定的类只产生一个对象,当然也允许在一定情况下灵活的改变对象的个数。那么怎么来实现单例模式呢?一个类的对象的产生是由类构造函数来完成的,如果想限制对象的产生,就要将构造函数变为私有的(至少是受保护的),使得外面的类不能通过引用来产生对象;同时为了保证类的可用性,就必须提供一个自己的对象以及访问这个对象的静态方法。(只有一个实例对象叫单实例了)

单例模式可分为有状态的和无状态的。有状态的单例对象一般也是可变的单例对象,多个单态对象在一起就可以作为一个状态仓库一样向外提供服务。没有状态的单例对象也就是不变单例对象,仅用做提供工具函数。

三、实现方法

饿汉式:

public class DumpDemo {

    private static DumpDemo instance = new DumpDemo();

    private DumpDemo() {}

    //静态工厂方法,提供一个供外部访问得到对象的静态方法

    public static DumpDemo getInstance() {

        return instance;

    }

}

懒汉式:

public class DumpDemo {

    private static DumpDemo instance = null;

    private DumpDemo() {}

    //静态工厂方法,提供一个供外部访问得到对象的静态方法

    public static synchronized DumpDemo getInstance() {

        if (instance == null) {

            instance = new DumpDemo();

        }

        return instance;

    }

}

先让我们来比较一下这两种实现方式。

首先他们的构造函数都是私有的,彻底断开了使用构造函数来得到类的实例的通道,但是这样也使得类失去了多态性(大概这就是为什么有人将这种模式称作单态模式)。 

在第二种方式中,对静态工厂方法进行了同步处理,原因很明显——为了防止多线程环境中产生多个实例;而在第一种方式中则不存在这种情况。(防止多线程过来的破坏)

在第二种方式中将类对自己的实例化延迟到第一次被引用的时候。而在第一种方式中则是在类被加载的时候实例化,这样多次加载会照成多次实例化。但是第二种方式由于使用了同步处理,在反应速度上要比第一种慢一些。

以上两种实现方式均失去了多态性,不允许被继承。还有另外一种灵活点的实现,将构造函数设置为受保护的,这样允许被继承产生子类。

PS:如果父类的构造方法是私有的话就不可以被继承了。注意哦单例模式中如果父类中用到了私有方法的话就不可以被构造了

GOF中认为最好的一种方式是维护一张存有对象和对应名称的注册表(可以使用HashMap来实现)

代码如下:

import java.util.HashMap;

public class DumpDemo {

    private static HashMap sinRegistry = new HashMap();

    static private DumpDemo s = new DumpDemo();

    protected DumpDemo() {}

    //静态工厂方法,提供一个供外部访问得到对象的静态方法

    public static DumpDemo getInstance(String name) {

        if(name == null)

            name = "Singleton";

        if(sinRegistry.get(name)==null){

            try{

                   sinRegistry.put(name , Class.forName(name).newInstance());

            }catch(Exception e)

            {

                   e.printStackTrace();

            }    

        }

         return (DumpDemo)(sinRegistry.get(name)); 

    }

     public void test()

     {

            System.out.println("getclasssuccess!");     

     }

}

class SingletonChild1 extends DumpDemo

{

       public SingletonChild1(){}

       static    public SingletonChild1 getInstance()

       {     //子类中可以获取到一个实例

              return (SingletonChild1)DumpDemo.getInstance("SingletonChild1");     

       }

       public void test()

       {

              System.out.println("getclasssuccess111!");

       }

}

 

摘自:http://blog.csdn.net/ai92/archive/2005/01/13/252369.aspx

 

阅读(686) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-06-14 23:13:44

注意单例模式只能实例化一个对象。验证方法就是 T t1 = T.getInstance(); T t2 = T.getInstance(); t1 == t2 是成立 的

chinaunix网友2010-06-14 22:40:57

我发现了随着知识的增长原来的问题已不在是我的问题了。所以我能力在提升这是好事更应当加大学习的力度了