`

二十四:单例模式

阅读更多
Java中的单例模式是指在程序的运行过程中,jvm中只存在一个实例。然而注意,Spring中配置的singleton是相对于IOC的工厂而言,一个IOC工厂里只有一个实例,然而在jvm中可能有多个实例,他们的参照物不同.


一:单例类有如下特点
A:只能有一个实例
B:必须自己创建自己的唯一实例
C:必须向系统提供自己的实例

二:饿汉式单例类
package cai.milenfan.basic.test; 

public class EagerSingleton { 
private static final EagerSingleton eagerSingleton = new EagerSingleton(); 
private EagerSingleton(){} 
public static EagerSingleton getInstance(){ 
return eagerSingleton; 
} 
} 


从上面的代码可以看出,饿汉式单例类在类被加载地,静态变量eagerSingleton会被初始化,此时类的私有构造子会被调用,这时单例类的唯一实例就被创建出来。 Java语言中单例类的一个重要特点就是构造子是私有的,从而避免外界利用构造子直接创建出多个实例,值得指出的是,由于构造子是私有的,因此此类不能被继承.

三:懒汉式单例类
package cai.milenfan.basic.test; 

public class LazySingleton { 
private static LazySingleton lazySingleton = null; 
private LazySingleton(){} 
synchronized public static LazySingleton getInstance(){ 
if(lazySingleton==null){ 
lazySingleton = new LazySingleton(); 
} 
return lazySingleton; 
} 
} 


在上面的懒汉式单例类里对静态工厂方法使用了同步,以处理多线程环境中多个线程同时首次引用此类时访问限制问题(有些设计师在这里建议使用所谓的"双重检查成例",应当指出在Java中不可以使用)

四:登记式单例类
登记式单例类是为了克服饿汉式单例类及懒汉式单例类均不可继承的缺点而设计的,请看下面的源码:
package cai.milenfan.basic.test; 

import java.util.HashMap; 

public class RegSingleton { 
static private HashMap regMap = new HashMap(); 
static{ 
RegSingleton x = new RegSingleton(); 
regMap.put(x.getClass().getName(),x); 
} 
protected RegSingleton(){} 

static public RegSingleton getInstance(String name){ 
if(name==null){ 
name="cai.milenfan.basic.test.RegSingleton"; 
} 
if(regMap.get(name)==null){ 
try { 
regMap.put(name,Class.forName(name).newInstance());
} catch (Exception e) {} 
} 
return (RegSingleton)regMap.get(name); 
} 
} 


它的子类如下,需要父类的帮助才能实例化:
package cai.milenfan.basic.test; 

public class RegSingletonChild extends RegSingleton{ 
public RegSingletonChild(){} 
static public RegSingletonChild getInstance(){ 
return (RegSingletonChild)RegSingleton.getInstance("cai.milenfan.basic.test.RegSingletonChild");
} 
} 



由于子类必须允许父类以构造子调用产生实例,因此子类的构造子必须是公开的.

五:一个实用的例子--属性管理器
大多数的系统都有一些配置常量,这些常量如果是存储在程序内部,那么每次个性这些常量都需要编译程序,将这些常量放在配置文件中,系统通过访问这个配置文件取得配置常量,就可以通过修改这个配置文件无需修改程序而达到更改系统配置的目的,下面将设计一个属性管理器类ConfigManager:
package cai.milenfan.basic.test; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.util.Properties; 

public class ConfigManager { 
//属性文件全名 
private static final String P_FILE = System.getProperty("user.dir") + File.separator + "singleton.properties"; 
//对应于属性文件的变量 
private File mFile = null; 
//最后修改时间 
private long lastModifyTime = 0; 
//属性文件所对应的属性对象的变量 
private Properties mProps = null; 
//唯一的实例 
private static ConfigManager instance = new ConfigManager(); 

private ConfigManager(){ 
mFile = new File(P_FILE); 
lastModifyTime = mFile.lastModified(); 
if(lastModifyTime==0){ 
System.out.println(P_FILE + " does not exit........"); 
} 
mProps = new Properties(); 
try { 
mProps.load(new FileInputStream(P_FILE)); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
//静态工厂方法,返回唯一实例 
synchronized public static ConfigManager getInstance(){ 
return instance; 
} 

//读取一个特定的属性 
final public Object getConfigItem(String key,Object value){ 
long newTime = mFile.lastModified(); 
if(newTime==0){ 
if(lastModifyTime==0){ 
System.out.println(P_FILE + " does not exit........"); 
}else{ 
System.out.println(P_FILE + " was deleted.........."); 
} 
return value; 
}else if(newTime>lastModifyTime){ 
mProps.clear(); 
try { 
mProps.load(new FileInputStream(P_FILE)); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
lastModifyTime = newTime; 
Object newvalue = mProps.get(key); 
if(newvalue==null){ 
return value; 
}else{ 
return newvalue; 
} 
} 
} 
singleton.properties是一个键值对应的文件: 
item1=how 
item2=are 
item3=you 


为什么这个类要使用单例模式:因为属性是系统的一种"资源",应当避免有多于一个的对象读取,特别是存储属性,此外,属性的读取可能会在很多地方发生,创建属性对象的地方应当放在哪里不是很清楚,换言之,属性管理器应当自己创建自己的实例,并且自己向系统全程提供这个实例,因此属性文件管理器ConfigManager应当是由一个单例进行负责的。
这个管理器类还有一个有意思的功能,即在每一次调用时,会检查属性文件是否被更新过,如果确实被更新过的话,管理器会自动重新加载属性文件,从而保证管理器的内容与属性文件的内容总是一致的.

六:Java语言中运用单例模式的例子
A:java.lang.Runtime
在每一个java应用程序里面,都有唯一一个Runtime对象,通过这个对象,应用程序可以与其运行环境发生相互作用,如执行外部命令(打开一个记事本),返回现在内存,运行垃圾收集器,加载动态库等等。
B:java.util.Introspector类
Sun提供了一个BeanBox系统,允许动态地加载JavaBean,并动态修改其性质.在这个系统中只需要一个Introspector对象,因此它被设计成单例..
C:java.awt.Toolkit
此类的getDefaultToolkit()提供唯一的实例,这个方法相当于懒汉式的单例方法,因此整个方法都是同步的.由于Toolkit是一个抽象类,因此如果其子类提供一个私有的构造子,那么其子类便是一个正常的单例类,而如果其子类作为具体实现提供一个公开的构造子,这时候这个具体子类便是"不完全"的单例类.
(注:getDefaultToolkit()方法实际上是一个模板方法,私有构造子是推迟到子类实现的剩余逻辑,根据子类对这个剩余逻辑的不同实现,子类就可以提供完全不同的行为.)
D:javax.swing.TimerQueue
这是一个不完全的单例类,再作介绍。
分享到:
评论

相关推荐

    Head First 设计模式 JAVA源码

    所有的设计模式Java实现。...第二十四讲:状态模式 第二十五讲:命令模式 第二十六讲:开放-封闭原则 第二十七讲:里氏转换原则 第二十八讲:依赖倒转原则 第二十九讲:迪米特法则 第三十讲:设计模式总结

    多线程单例模式并发访问

    ### 多线程单例模式并发访问 #### 一、多线程基础概念 在讨论多线程单例模式及并发访问之前,我们先来了解一些基本概念。 **进程**和**线程**是计算机科学中的两个核心概念,它们之间的关系紧密而复杂。 - **进程...

    二十四种设计模式全实现_含图解

    《二十四种设计模式全实现_含图解》是一个综合性的学习资料,包含了24种经典的设计模式,旨在帮助开发者更好地理解和应用这些模式。 1. **工厂模式**:工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳...

    二十二种设计模式.pdf

    二、单例模式 三、工厂方法模式 四、建造者模式 五、适配器模式 六、桥接模式 七、组合模式 八、装饰器模式 九、外观模式 十、享元模式 十一、代理模式 十二、命令模式 十三、责任链模式 十四、解释器模式 十五、...

    设计模式PPT.rar

    22第二十二讲备忘录模式 23第二十三讲状态模式 24第二十四讲命令模式 25第二十五讲访问者模式 26第二十六讲开放封闭原则 27第二十七讲单一职责原则 28第二十八讲里氏代换原则 29第二十九讲依赖倒转原则 30第三十讲...

    二十三种设计模式通俗理解

    ### 二十三种设计模式通俗理解 #### 1. FACTORY (工厂模式) 工厂模式是一种常用的软件设计模式,它的核心思想在于将实例化的责任交给一个专门的类——工厂类。这样做的好处是用户无需了解创建对象的具体过程,只...

    设计模式PPT合集

    十四、策略模式 策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用它的客户。 十五、模板方法模式 模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟...

    C++设计模式

    (一)简单工厂模式 2 (二)策略模式 4 策略与工厂结合 6 单一职责原则 6 开放――封闭原则 6 里氏代换原则 7 依赖倒转原则 7 (三)装饰模式 7 (四)代理模式 9 (五)工厂方法模式 11 ...(二十四)访问者模式 61

    guide_to_php_design_pattern_zh.pdf

    - 第十四章:策略模式 - 第十五章:模板方法模式 - 第十六章:迭代器模式 - 第十七章:观察者模式 - 第十八章:命令模式 - **翻译团队**:本书的中文版由PHPChina成员翻译完成,各章节分别由不同的译者负责。 ...

    DesignPattern

    --第五章:单例模式(Singleton) 本质:控制实例数目 --第六章:工厂方法模式(Factory Method) 本质:延迟到子类类选择实现(选择单个产品的实现) --第七章:抽象工厂模式(Abstract Factory) 本质:选择产品簇的实现 -...

    PHP设计模式介绍.

    #### 第四章:单例模式—确保唯一性的关键 单例模式是一种常用的创建型设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。这在需要控制资源访问(如数据库连接)或配置信息的地方特别有用。单例模式的...

    长久以来对设计模式的重大误解

    它们是在不同场景下经过验证的、良好的设计实践,如工厂模式、单例模式、观察者模式等。 误区一:设计模式就是模板代码。很多人误以为设计模式提供了可以直接复制粘贴的代码片段,实际上,设计模式更强调思想和结构...

    二十三种设计模式小手册

    这些模式是由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位大师,也被称为Gang of Four (GOF),在他们的经典著作《设计模式:可复用面向对象软件的基础》中提出的。本小手册详细阐述了这二十三种...

    Head First Design Patterns(All in one).pdf

    12. **第十二章:模式中的模式:复合模式** - 解释了如何将多个设计模式结合使用以解决更复杂的问题。 - 通过例子展示了复合模式的实际应用。 13. **第十三章:现实世界中的模式:更好的生活模式** - 探讨了...

    DesignPattern:设计模式演示代码

    设计模式 丛林设计模式系列 订正 2021/04/04:为虚基类添加...设计模式(九)-单例模式 博客地址: : 10.设计模式(十)-适配器模式 博客地址: : 11.设计模式(十一)-合理模式 博客地址: : 12.设计模式(十二

    java设计模式

    **定义**:单例模式是一种创建型设计模式,其目的是确保某个类只有一个实例,并且提供一个全局访问点来获取该实例。 **应用场景**:比如家庭中的唯一父亲角色,所有的孩子只需要称呼“爸爸”就能找到同一个个体。 ...

    二十三种设计模式Gof 代码

    GOF(Gang of Four)设计模式是由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位作者在《设计模式:可复用面向对象软件的基础》一书中提出的,共包含了23种经典的设计模式。这些模式为软件开发提供...

    Java中的23种设计模式

    #### 十四、命令模式 **定义**: 命令模式将一个请求封装为一个对象,从而使用户可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 **优点**: - 请求发送者与请求接收者解耦; -...

    二十三种设计模式【PDF版】

    设计模式之 Singleton(单态/单件) 阎宏博士讲解:单例(Singleton)模式 保证一个类只有一个实例,并提供一个访问它的全局访问点 设计模式之 Factory(工厂方法和抽象工厂) 使用工厂模式就象使用 new 一样频繁. ...

    C#设计模式PDF 电子书

    一、单例模式(Singleton) 单例模式确保一个类只有一个实例,并提供一个全局访问点。在C#中,可以通过静态成员或者 Lazy<T> 类来实现单例,以保证线程安全并延迟初始化。 二、工厂模式(Factory) 工厂模式是一种...

Global site tag (gtag.js) - Google Analytics