java单例模式还有什么?JAVA单例模式有哪些
今天给各位分享java单例模式还有什么的知识,其中也会对JAVA单例模式有哪些进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
Java模式设计之单例模式(一)
作为对象的创建模式[GOF ]单例模式确保某一个类只有一个实例而且自行实例化并向整个系统提供这个实例这个类称为单例类
单例模式的要点
单例单例
显然单例模式的要点有三个一是某各类只能有一个实例二是它必须自行创建这个事例三是它必须自行向整个系统提供这个实例在下面的对象图中有一个单例对象而客户甲客户乙和客户丙是单例对象的三个客户对象可以看到所有的客户对象共享一个单例对象而且从单例对象到自身的连接线可以看出单例对象持有对自己的引用
资源管理
一些资源管理器常常设计成单例模式
在计算机系统中需要管理的资源包括软件外部资源譬如每台计算机可以有若干个打印机但只能有一个Printer Spooler以避免两个打印作业同时输出到打印机中每台计算机可以有若干传真卡但是只应该有一个软件负责管理传真卡以避免出现两份传真作业同时传到传真卡中的情况每台计算机可以有若干通信端口系统应当集中管理这些通信端口以避免一个通信端口同时被两个请求同时调用
需要管理的资源包括软件内部资源譬如大多数的软件都有一个(甚至多个)属性(properties)文件存放系统配置这样的系统应当由一个对象来管理一个属性文件
需要管理的软件内部资源也包括譬如负责记录网站来访人数的部件记录软件系统内部事件出错信息的部件或是对系统的表现进行检查的部件等这些部件都必须集中管理不可政出多头
这些资源管理器构件必须只有一个实例这是其一它们必须自行初始化这是其二允许整个系统访问自己这是其三因此它们都满足单例模式的条件是单例模式的应用
一个例子 Windows回收站
Windows x以后的视窗系统中都有一个回收站下图就显示了Windows的回收站
在整个视窗系统中回收站只能有一个实例整个系统都使用这个惟一的实例而且回收站自行提供自己的实例因此回收站是单例模式的应用
双重检查成例
在本章最后的附录里研究了双重检查成例双重检查成例与单例模式并无直接的关系但是由于很多C语言设计师在单例模式里面使用双重检查成例所以这一做法也被很多Java设计师所模仿因此本书在附录里提醒读者双重检查成例在Java语言里并不能成立详情请见本章的附录
单例模式的结构
单例模式有以下的特点
……单例类只可有一个实例
……单例类必须自己创建自己这惟一的实例
……单例类必须给所有其他对象提供这一实例
虽然单例模式中的单例类被限定只能有一个实例但是单例模式和单例类可以很容易被推广到任意且有限多个实例的情况这时候称它为多例模式(Multiton Pattern)和多例类(Multiton Class)请见专题多例(Multiton)模式与多语言支持一章单例类的简略类图如下所示
由于Java语言的特点使得单例模式在Java语言的实现上有自己的特点这些特点主要表现在单例类如何将自己实例化上
饿汉式单例类饿汉式单例类是在Java语言里实现得最为简便的单例类下面所示的类图描述了一个饿汉式单例类的典型实现
从图中可以看出此类已经自已将自己实例化
代码清单饿汉式单例类
public class EagerSingleton{ private static final EagerSingleton m_instance= new EagerSingleton()/***私有的默认构造子*/ private EagerSingleton(){}/***静态工厂方法*/ public static EagerSingleton getInstance()
{
Java与模式return m_instance}
读者可以看出在这个类被加载时静态变量m_instance会被初始化此时类的私有构造子会被调用这时候单例类的惟一实例就被创建出来了
Java语言中单例类的一个最重要的特点是类的构造子是私有的从而避免外界利用构造子直接创建出任意多的实例值得指出的是由于构造子是私有的因此此类不能被继承
懒汉式单例类
与饿汉式单例类相同之处是类的构造子是私有的与饿汉式单例类不同的是懒汉式单例类在第一次被引用时将自己实例化如果加载器是静态的那么在懒汉式单例类被加载时不会将自己实例化如下图所示类图中给出了一个典型的饿汉式单例类实现
代码清单懒汉式单例类
package javapatterns singleton demos public class LazySingleton{ private static LazySingleton m_instance= null/***私有的默认构造子保证外界无法直接实例化*/ private LazySingleton(){}/***静态工厂方法返还此类的惟一实例*/ synchronized public static LazySingleton getInstance()
{ if(m_instance== null)
{ m_instance= new LazySingleton()} return m_instance}
读者可能会注意到在上面给出懒汉式单例类实现里对静态工厂方法使用了同步化以处理多线程环境有些设计师在这里建议使用所谓的双重检查成例必须指出的是双重检查成例不可以在Java语言中使用不十分熟悉的读者可以看看后面给出的小节
同样由于构造子是私有的因此此类不能被继承饿汉式单例类在自己被加载时就将自己实例化即便加载器是静态的在饿汉式单例类被加载时仍会将自己实例化单从资源利用效率角度来讲这个比懒汉式单例类稍差些
从速度和反应时间角度来讲则比懒汉式单例类稍好些然而懒汉式单例类在实例化时必须处理好在多个线程同时首次引用此类时的访问限制问题特别是当单例类作为资源控制器在实例化时必然涉及资源初始化而资源初始化很有可能耗费时间这意味着出现多线程同时首次引用此类的机率变得较大
饿汉式单例类可以在Java语言内实现但不易在C++内实现因为静态初始化在C++里没有固定的顺序因而静态的m_instance变量的初始化与类的加载顺序没有保证可能会出问题这就是为什么GoF在提出单例类的概念时举的例子是懒汉式的他们的书影响之大以致Java语言中单例类的例子也大多是懒汉式的实际上本书认为饿汉式单例类更符合Java语言本身的特点
登记式单例类
登记式单例类是GoF为了克服饿汉式单例类及懒汉式单例类均不可继承的缺点而设计的本书把他们的例子翻译为Java语言并将它自己实例化的方式从懒汉式改为饿汉式只是它的子类实例化的方式只能是懒汉式的这是无法改变的如下图所示是登记式单例类的一个例子图中的关系线表明此类已将自己实例化
代码清单登记式单例类
import java util HashMap public class RegSingleton{ static private HashMap m_registry= new HashMap() static{ RegSingleton x= new RegSingleton() m_registry put( x getClass() getName() x)}/***保护的默认构造子*/ protected RegSingleton(){}/***静态工厂方法返还此类惟一的实例*/ static public RegSingleton getInstance(String name)
{ if(name== null)
{ name= javapatterns singleton demos RegSingleton} if(m_registry get(name)== null)
{ try{ m_registry put( name Class forName(name) newInstance())} catch(Exception e)
{ System out println( Error happened)} return(RegSingleton)(m_registry get(name))}/***一个示意性的商业方法*/ public String about()
{ return Hello I am RegSingleton}它的子类RegSingletonChild需要父类的帮助才能实例化下图所示是登记式单例类子类的一个例子图中的关系表明此类是由父类将子类实例化的
下面是子类的源代码
代码清单登记式单例类的子类
import java util HashMap public class RegSingletonChild extends RegSingleton{ public RegSingletonChild(){}/***静态工厂方法*/ static public RegSingletonChild getInstance()
{ return(RegSingletonChild)
RegSingleton getInstance( javapatterns singleton demos RegSingletonChild)}/***一个示意性的商业方法*/ public String about()
{ return Hello I am RegSingletonChild}
在GoF原始的例子中并没有getInstance()方法这样得到子类必须调用的getInstance(String name)方法并传入子类的名字因此很不方便本章在登记式单例类子类的例子里加入了getInstance()方法这样做的好处是RegSingletonChild可以通过这个方法返还自已的实例而这样做的缺点是由于数据类型不同无法在RegSingleton提供这样一个方法由于子类必须允许父类以构造子调用产生实例因此它的构造子必须是公开的这样一来就等于允许了以这样方式产生实例而不在父类的登记中这是登记式单例类的一个缺点
lishixinzhi/Article/program/Java/gj/201311/27416JAVA单例模式有哪些
一、懒汉式单例
在类加载的时候不创建单例实例。只有在第一次请求实例的时候的时候创建,并且只在第一次创建后,以后不再创建该类的实例。
public class LazySingleton{
/**
*私有静态对象,加载时候不做初始化
*/
private static LazySingleton m_intance=null;
/**
*私有构造方法,避免外部创建实例
*/
private LazySingleton(){
}
/**
*静态工厂方法,返回此类的唯一实例.
*当发现实例没有初始化的时候,才初始化.
*/
synchronized public static LazySingleton getInstance(){
if(m_intance==null){
m_intance=new LazySingleton();
}
return m_intance;
}
}
二、饿汉式单例
在类被加载的时候,唯一实例已经被创建。
public class EagerSingleton{
/**
*私有的(private)唯一(static final)实例成员,在类加载的时候就创建好了单例对象
*/
private static final EagerSingleton m_instance= new EagerSingleton();
/**
*私有构造方法,避免外部创建实例
*/
private EagerSingleton(){
}
/**
*静态工厂方法,返回此类的唯一实例.
*@return EagerSingleton
*/
public static EagerSingleton getInstance(){
return m_instance;
}
}
**************************************************************************************懒汉方式,指全局的单例实例在第一次被使用时构建;
饿汉方式,指全局的单例实例在类装载时构建
**************************************************************************************
三、登记式单例
这个单例实际上维护的是一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从工厂直接返回,对于没有登记的,则先登记,而后返回。
public class RegSingleton{
/**
*登记薄,用来存放所有登记的实例
*/
private static Map<String, RegSingleton> m_registry= new HashMap();
//在类加载的时候添加一个实例到登记薄
static{
RegSingleton x= new RegSingleton();
m_registry.put(x.getClass().getName(), x);
}
/**
*受保护的默认构造方法
*/
protected RegSingleton(){
}
/**
*静态工厂方法,返回指定登记对象的唯一实例;
*对于已登记的直接取出返回,对于还未登记的,先登记,然后取出返回
*@param name
*@return RegSingleton
*/
public static RegSingleton getInstance(String name){
if(name== null){
name="RegSingleton";
}
if(m_registry.get(name)== null){
try{
m_registry.put(name,(RegSingleton) Class.forName(name).newInstance());
} catch(InstantiationException e){
e.printStackTrace();
} catch(IllegalAccessException e){
e.printStackTrace();
} catch(ClassNotFoundException e){
e.printStackTrace();
}
}
return m_registry.get(name);
}
/**
*一个示意性的商业方法
*@return String
*/
public String about(){
return"Hello,I am RegSingleton!";
}
}
java常用的几种单例模式(懒汉式,饿汉式
单件模式用途:
单件模式属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用。
单件模式能够保证某一类型对象在系统中的唯一性,即某类在系统中只有一个实例。它的用途十分广泛,打个比方,我们开发了一个简单的留言板,用户的每一次留言都要将留言信息写入到数据库中,最直观的方法是没次写入都建立一个数据库的链接。这是个简单的方法,在不考虑并发的时候这也是个不错的选择。但实际上,一个网站是并发的,并且有可能是存在大量并发操作的。如果我们对每次写入都创建一个数据库连接,那么很容易的系统会出现瓶颈,系统的精力将会很多的放在维护链接上而非直接查询操作上。这显然是不可取的。
如果我们能够保证系统中自始至终只有唯一一个数据库连接对象,显然我们会节省很多内存开销和cpu利用率。这就是单件模式的用途。当然单件模式不仅仅只用于这样的情况。在《设计模式:可复用面向对象软件的基础》一书中对单件模式的适用性有如下
1、当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2、当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
下面对单件模式的懒汉式与饿汉式进行简单介绍:
1、饿汉式:在程序启动或单件模式类被加载的时候,单件模式实例就已经被创建。
2、懒汉式:当程序第一次访问单件模式实例时才进行创建。
如何选择:如果单件模式实例在系统中经常会被用到,饿汉式是一个不错的选择。
好了,文章到此结束,希望可以帮助到大家。