`

二十四:单例模式

阅读更多
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实现。...第二十四讲:状态模式 第二十五讲:命令模式 第二十六讲:开放-封闭原则 第二十七讲:里氏转换原则 第二十八讲:依赖倒转原则 第二十九讲:迪米特法则 第三十讲:设计模式总结

    设计模式PPT.rar

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

    设计模式-7种开发语言(C#、JAVA、JavaScript、C++、Python、Go、PHP).pdf

    24种设计模式的入门,整合7种开发语言的代码示例。 ...第一节 设计模式:学习顺序 第二节 简单工厂模式 第三节 工厂方法模式 第四节 抽象工厂模式 第五节 单例模式 ...第二十四节 责任链模式 第二十五节 解释器模式

    C++设计模式

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

    DesignPattern

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

    DesignPattern:设计模式演示代码

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

    设计模式PPT

    05第五讲单例模式 06第六讲原型模式 ,,,, 25第二十五讲:访问者模式 26第二十六讲:基础一开放封闭原则 27第二十七讲:基础二单一职责原则 ,,, 31第三十一讲:UML类图(上) 32第三十二讲:UML类图(下)

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

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

    完整学习笔记:《剑指offer》Java版代码实现

    目录 题号 题目及题解 测试示例 第二题 单例设计模式 测试2 第三题 二维码中找到目标值 测试3 第四题 替换字符串中的空格 测试4 ...第二十四题 后序遍历二叉搜索树 测试24 第二十五题 二叉树中和为某值的路径

    mohuishou.github.io:Mohuishou的博客

    Go设计模式01-单例模式 Go设计模式02-工厂模式&DI容器 Go设计模式03-建造者模式 Go设计模式04-原型模式 Go设计模式05-创建型模式总结 结构型 Go设计模式06-代理模式(generate实现类似动态代理) Go设计模式07-桥接...

    Java基础知识点总结.docx

    单例设计模式:★★★★★ 156 工厂模式★★★★★ 159 抽象工厂模式★★★★★ 163 建造者模式 170 原型模式 177 适配器模式 182 桥接模式 188 过滤器模式 192 组合模式 193 装饰器模式★★★★★ 196 外观模式 201...

    大型网页游戏架构书

    单例模式; 外观模式. Decorator 模式: 五.事件管理(GameEvent 包) 划分不同的情节,用不同的类来描述情节。包括不同的任务。 初步想法:写出不同的事件,每一个事件就关于一个故事情节,引发场景动画,引发一些...

    java8源码-LambdaPractice:《java8实战》代码练习

    java8 源码 ...2、添加设计模式代码实践,装饰模式decorator,工厂模式factory,单例模式singletonInstance ####第七周完成工作 1、第11章CompletableFuture:组合式异步编程代码实战 2、添加包desig

    java面试题库2021.pdf

    目录 一、 JavaSE 部分 1、 Java 基础 ①Java 基础部分(基本语法, Java 特性等) ②关键字 ③面向对象 ...①单例模式 3、 行为型模式 ①策略模式 ②观察者模式 4、 所有模式汇总 十、 场景题 十一、 UML

    编程新手真言......

    完善前二十页 -------------------------------------------------------------------------------------------------------------- 目 录 第一部分 9 前 言 9 By Chenyi 9 By Minlearn 10 导 读 14 任何语言都是有...

    JAVA面试题收录

    文章目录一、JavaSE基础二、JavaWeb部分三、框架部分四、数据库部分五、程序算法六、JVM调优七、Java优化八、Redis相关九、Nginx相关十、WebService相关十一、其他 一、JavaSE基础 接口和抽象类的异同点 重载...

    一个java正则表达式工具类源代码.zip(内含Regexp.java文件)

    * \0mnn The character with octal value 0mnn (0 , 0 ) \0mnn 十进制数 0mnn (0 , 0 ) * \xhh The character with hexadecimal value 0xhh \xhh 十六进制数 0xhh * \\uhhhh The character with ...

    Java核心技术II(第8版)

    第十二章 XML 2.1 XML概述 2.1.1 XML文档的结构 2.2 解析XML文档 2.3 验证XML文档 2.3.1 文档类型定义 2.3.2 XML Schema 2.3.3 实用示例 2.4 使用XPath来定位信息 2.5 使用名字空间 2.6 流机制解析器 2.6.1 使用SAX...

    最新JAVA编程题全集_50题及答案

    写一个单例模式(遇到两次) public class Test { private Test(){} private static Test test; public static Test getInstance() { if(test==null) { test = new Test(); } return test; }} 5. //统计...

    思库教育PHP零基础培训+进阶课程+PHP项目开发实战 21G PHP零基础学习视频教程.txt

    │ │ ├[北京思库教育]第68集 设计模式_单例.avi │ │ ├[北京思库教育]第69集 设计模式_工厂.avi │ │ ├[北京思库教育]第70集 序列化与反序列化.avi │ │ ├[北京思库教育]第71集 属性重载.avi │ │ └[北京...

Global site tag (gtag.js) - Google Analytics