`
行者买刀
  • 浏览: 191496 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

设计模式之略见一斑(单例模式singleton)

    博客分类:
  • J2SE
阅读更多

单例模式是属于比较常用的一例,一个类(class)在内存中只有一个实例。

常用方式如下:

 第一种(饿汉式):

public class Singleton {

  private Singleton(){}

  //在自己内部定义自己一个实例,是不是很奇怪?
  //注意这是private 只供内部调用

  private static Singleton instance = new Singleton();

  //这里提供了一个供外部访问本class的静态方法,可以直接访问  
  public static Singleton getInstance() {
    return instance;   
   } 
} 

 

 

第二种方式:(懒汉式)

public class Singleton { 

  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     
  if (instance==null)
    instance=new Singleton();
  return instance;   } 

} 

 

比较安全的使用方式是第一种private static Singleton instance = new Singleton();

 

单例的陷井:

   多个虚拟机

当单例类被运行在多个虚拟机下的时候,在每个虚拟机都可以创建一个实例对歇脚。像使用了EJB,JINI,RMI技术的分布式系统的时候,因为中间件屏蔽了分布式系统在物理上的差异,这个时候想知道在哪个虚拟机下运行着哪个单例对象很困难。因此在使用分布式技术时,应该避免使用

 

   多个类加载器

当存在多个类加载器,即使它们加载的相同包名,相同类名甚至每个字节都完全相同的类,也会被区别对待的。因为不同的类加载器会使用不同的命名空间来区分同一个类,因此,单例类在多加载器的环境下会产生多个单例对象。也许你认为出现多个类加载器的情况不多,其实多个类加载器存在的情况不少,在很多J2EE服务器上允许存在多个SERVLET引擎,而每个引擎是采用不同的类加载器的,浏览器的APPLET小程序通过网络加载类的时候,由于安全因素,采用的是特殊类加载器,等等。

   在这种情况,由状态的单例模式也会给系统带来隐患。因此除非系统由协调机制,在一般情况下不要使用存在状态的单例模式。

 

 

   错误的同步处理

在使用上面介绍的懒汉式单模式的时候,同步得理恰当与否也是很,不然要能达不到想要的单例效果,还可能引发死锁等。因此在使用懒汉式单例模式时一定要对同步有所了解,不过使用饿汉式单例模式就可以避免这个问题。

 

   子类破坏了对象控制

如果构造器变得不再私有,就有可能失去对对象的控制

 

   串行化(可序列化)

为了使一个单例类变成可串行化的,仅仅在声明中添加“implements Serializable"是不够的,因为一个串行化的对象在每次反串行化的时候,都会创建一个新的对象,而不仅仅是一个对原有对象的引用,为了防止这种情况,可以在单例类中加入readResolve方法

public final class Singleton implements Serializable{   
    private Singleton () { }   
    private static final Singleton INSTANCE = new Singleton ();   
    public static Singleton getInstance() { return INSTANCE; }   
    private Object readResolve() throws ObjectStreamException {    
      return INSTANCE;   
   }   
}  

 对象的反串行化并不仅局限于上述方式,还存在基于 XML模式的对象串行化方式,这种方式也存在上述的问题,所以在使用的时候还要格外小心。

 

 

分享到:
评论
5 楼 Andy19890601 2011-04-10  
这些代码都是《Head First 设计模式》上的,这本书确实很好
4 楼 行者买刀 2010-11-03  
第一次
jibin6693923 写道
请问
构造方法定义为私有,还可以有子类吗?
在子类里怎么创建父类的对象?


单例模式的初衷就是为了能让在内存中只有一个实例,如果子类继承父类的话,那么内存中就有两个类似行为的对象了。所以构造私有,子类是不能继承的。其实我们完全可以把单例类定义为final类。
3 楼 jibin6693923 2010-10-28  
请问
构造方法定义为私有,还可以有子类吗?
在子类里怎么创建父类的对象?
2 楼 行者买刀 2010-03-02  
EyejavaLi 写道
# //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次      
#   //使用时生成实例,提高了效率!

不知道生成实例跟生成对象有什么区别

不都一样?哈哈,是有些多余。改过改过,谢谢提醒。
1 楼 EyejavaLi 2010-03-02  
# //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次      
#   //使用时生成实例,提高了效率!

不知道生成实例跟生成对象有什么区别

相关推荐

    设计模式之略见一斑(Observer观察者模式)

    NULL 博文链接:https://lgh3292.iteye.com/blog/600905

    21种设计模式略见一斑

    NULL 博文链接:https://teddywang.iteye.com/blog/769122

    循环冗余校验-概念 算法 应用

    CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,...例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。

    CRC16或32校验

    CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,编码...例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑

    CRC算法和实现

    例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。 差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能...

Global site tag (gtag.js) - Google Analytics