beauty_beast
上善若水 厚德载物
导航
BlogJava
首页
新随笔
联系
聚合
管理
<
2005年8月
>
日
一
二
三
四
五
六
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
常用链接
我的随笔
我的评论
我的参与
最新评论
随笔分类
(25)
AppServer(3)
HTML/CSS(1)
J2EE(1)
JavaScript
java基础(4)
oracle开发应用(2)
oracle日常管理(4)
oracle调优(3)
OS(1)
人生感悟(1)
开源框架(5)
随笔档案
(28)
2006年10月 (2)
2006年9月 (2)
2006年7月 (1)
2006年6月 (2)
2006年5月 (4)
2006年4月 (2)
2006年3月 (6)
2006年2月 (6)
2005年10月 (1)
2005年8月 (2)
收藏夹
(2)
开源框架(2)
好友链接
java开发者
技术资源站点
ORACLE技术用户讨论组
搜索
积分与排名
积分 - 76990
排名 - 720
最新评论
1. re: 基于log4j实现统一日志管理
评论内容较长,点击标题查看
--BadMan03
阅读排行榜
1. oracle 物化视图(8695)
2. 采用HTTP协议上传文件实现(java)(7114)
3. Spring学习笔记二----Web MVC(5718)
4. Spring框架学习一----基本配置(5621)
5. 基于log4j实现统一日志管理(4976)
学习设计模式之singleton模式
Posted on 2005-08-18 21:09
柳随风
阅读(535)
评论(1)
编辑
收藏
本文只是本人的学习总结,目的希望能和大家一起交流分享,顺便备忘,如有不正确的地方,欢迎指正。
singleton模式我们在开发时经常会使用到,比如将一个系统运行时的初始配置数据封装成一个配置对象,在系统初始化时实例化该对象,因为对于整个系统运行时该对象的成员都是不变的,如果只需要一个实例就行,这样对系统的性能是很有益的。往往该配置对象都是和资源密切相关的(例如 数据库连接、文件等等),但是如果采用该模式设计、编码不当,常会造成资源泄漏,甚至更严重的问题(我的最近一个项目就出现过问题)。
一个简单的单实例模式实现如下:
/**/
/*
* Created on 2005-8-18
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package study.design.singleton;
/**/
/*
*
* @author liusuifeng
*
* TODO To change the template for this generated type comment go to Window -
* Preferences - Java - Code Style - Code Templates
*/
public
class
TestSingleTon
{
private
static
TestSingleTon test
=
null
;
private
TestSingleTon()
{
System.
out
.println(
"
contructor has been inited
"
);
}
public
static
synchronized TestSingleTon getInstance()
{
if
(test
==
null
)
{
test
=
new
TestSingleTon();
}
return
test;
}
}
这样的定义在单线程应用中时没有问题的,但是如果是多线程访问的话实际就不是单实例了:
举个简单例子:
/*
* Created on 2005-8-18
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package study.design.singleton;
/*
*
* @author liusuifeng
*/
public
class
TestThread extends Thread {
public
void
run(){
TestSingleTon test
=
TestSingleTon.getInstance();
System.
out
.println(
"
TestSingleTon====
"
+
test);
}
public
static
void
main(String[] args){
for
(
int
i
=
0
;i
<
10
;i
++
){
TestThread mthread
=
new
TestThread();
mthread.start();
}
}
}
运行时系统输出如下:
TestSingleTon====study.design.singleton.TestSingleTon@107077e
TestSingleTon====study.design.singleton.TestSingleTon@7ced01
TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
TestSingleTon====study.design.singleton.TestSingleTon@1ac04e8
呵呵,单实例变成三实例了,所以我们编码、设计时一定要考虑该对象的调用环境,保险起见,我们可以加上同步,修改原来的实现,将方法加上同步:
public
static
synchronized TestSingleTon getInstance()
{
if
(test
==
null
)
{
test
=
new
TestSingleTon();
}
return
test;
}
执行测试代码输出:
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
TestSingleTon====study.design.singleton.TestSingleTon@11a698a
这样就保证了多线程调用时也只有一个实例。
呵呵,这样就能保证在同一虚拟机上只有一个实例了吗?
如果对象是个可序列化的对象呢?
/*
* Created on 2005-8-18
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package study.design.singleton;
import java.io.Serializable;
/*
*
* @author liusuifeng
*
* TODO To change the template for this generated type comment go to Window -
* Preferences - Java - Code Style - Code Templates
*/
public
class
TestSingleTon implements Serializable {
private
static
TestSingleTon test
=
null
;
private
TestSingleTon() {
System.
out
.println(
"
contructor has been inited
"
);
}
public
static
synchronized TestSingleTon getInstance() {
if
(test
==
null
) {
test
=
new
TestSingleTon();
}
return
test;
}
}
下面的方法就又偷出一个实例出来:
/*
* Created on 2005-8-18
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package study.design.singleton;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/*
*
* @author liusuifeng
*
* TODO To change the template for this generated type comment go to Window -
* Preferences - Java - Code Style - Code Templates
*/
public
class
TestSerialObject {
private
void
writeObject() {
TestSingleTon tempobj
=
TestSingleTon.getInstance();
ObjectOutputStream oos
=
null
;
try
{
oos
=
new
ObjectOutputStream(
new
FileOutputStream(
"
c:\\object.data
"
));
oos.writeObject(tempobj);
}
catch
(FileNotFoundException e1) {
e1.printStackTrace();
}
catch
(IOException e1) {
e1.printStackTrace();
}
finally
{
try
{
oos.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
public
Object getSerialObject() {
Object o
=
new
Object();
ObjectInputStream ois
=
null
;
writeObject();
try
{
ois
=
new
ObjectInputStream(
new
FileInputStream(
"
c:\\object.data
"
));
o
=
ois.readObject();
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
finally
{
try
{
ois.close();
}
catch
(IOException e1) {
e1.printStackTrace();
}
}
return
o;
}
public
static
void
main(String[] args) {
TestSerialObject to
=
new
TestSerialObject();
Object obj1
=
to.getSerialObject();
System.
out
.println(obj1.equals(TestSingleTon.getInstance()));
}
}
运行输出如下:
contructor has been inited
false
学习总结如下:
采用单实例模式时设计编码时要尽可能的多考虑其调用场景,在实现中规避不应该出现的多实例情形。
Feedback
#
re: 学习设计模式之singleton模式
回复
更多评论
2005-08-18 22:03 by
Rocky
呵呵,我再补充一点,关于单实例。
版主例子中给了单实例的一种实现:
public class TestClass
{
private static TestClass instance;
private TestClass(){}
public static TestClass()
{
if( null != instance) instance = new TestClass();
return instance;
}
public void testA(){};
public void testB(){};
}
这种是比较常用的,但有这么一个问题。即该类一旦实例化,那么将永远不能被回收。即使你将 instance 赋成 null,也不能将该类清除掉。
还有一种单实例模式,见下:
public class TestClass
{
private String aaa;
public TestClass(){
//初始化单实例中的一些变量
aaa = .....;
}
public static void testA(){
//针对aaa的操作
}
public static void testB(){}{
//针对aaa的操作
}
}
即将方法声明为 static 方法。这样声明之后,那么针对aaa的操作的所有行为也将遵循单实例模式。
这种方式的优点就是类的实例可以随时销毁。但有个缺点:即每次调用都需要创建一个实例出来,有时间上的开销。
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理
Powered by:
BlogJava
Copyright © 柳随风