kapok
垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!
BlogJava
::
首頁
::
新隨筆
::
聯系
::
聚合
::
管理
::
455 隨筆 :: 0 文章 :: 76 評論 :: 0 Trackbacks
<
2005年4月
>
日
一
二
三
四
五
六
27
28
29
30
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
1
2
3
4
5
6
7
常用鏈接
我的隨筆
我的評論
我的參與
最新評論
留言簿
(28)
給我留言
查看公開留言
查看私人留言
隨筆分類
.NET(10)
(rss)
ALL(464)
(rss)
AppFuse(20)
(rss)
CorBa(2)
(rss)
Eclipse技巧和插件等(7)
(rss)
English(10)
(rss)
ERP(3)
(rss)
HibernateAndSpring(82)
(rss)
J2EE(290)
(rss)
J2SE(27)
(rss)
JB(2)
(rss)
JBOSS(4)
(rss)
JDO(1)
(rss)
Linux(7)
(rss)
Oracle(9)
(rss)
PetStore
(rss)
Struts(9)
(rss)
UML與RUP(13)
(rss)
Web Services(8)
(rss)
Weblogic Portal(72)
(rss)
XDoclet(6)
(rss)
個人項目所需資料(8)
(rss)
辦公自動化(2)
(rss)
點滴(1)
(rss)
程序員生活(10)
(rss)
行業知識(15)
(rss)
軟件工程和項目管理(32)
(rss)
軟件測試(1)
(rss)
隨手貼(5)
(rss)
面試(4)
(rss)
隨筆檔案
2005年9月 (18)
2005年8月 (39)
2005年7月 (42)
2005年6月 (49)
2005年5月 (70)
2005年4月 (116)
2005年3月 (121)
Corba
EAI
Bea Portal相關
dnnchina
Enterprise Java Research Library
xoops
泡泡-博客
Online Document
Bea Resource Center
WebLogic Online Help_ZH
Open Source
exo portal
Groller
Mule
pow2toolkit
xpetstore
開源
Portal
huihoo JSR168
灰狐
RSS Links
.Text 0.958 安裝&問題解決方案
All about Blog and RSS
RSS links
Weblogic凈化貼
Weblogic
WL Portal FAQs
WLP FAQss
不錯的鏈接
chenyun2000
CSDN專欄作家
Eclipse Live Forum
firebody
gigix
glchengang
IT人
JavaEye
JavaPassion
michael
ODMG
oracle_tech
Pattern在線查詢手冊
querycriteria
rosen
spring reference
上海電子地圖
兔八哥
兔子
思維導圖
范凱的廢紙簍
工具集合
AppFuse
數據倉庫相關
blog on dw
BRM業務參考模型
chinabi
china-bi
CNOUG DW
datawarehouse
dbazine
dmreview
DW 信息目錄
dw-institute
DWWAY
ewsolutions
flymouse
inmoncif
intelligententerprise
isomebody
IT售前論壇
rkimball
SummerRain
tdan
商業智能
頭頭腦腦
快語綜合
精進門
搜索
最新評論
1.?re: Java中的URLEncoder和URLDecoder類
asdfsdf
--sadf
2.?re: 面試題,做出來3萬月薪[未登錄]
很強,就是這樣的邏輯@此外
--TEST
3.?re: MKS Toolkit[未登錄]
政治
--s
4.?re: Java 遠程方法調用(RMI)
if (r instanceof Meeting )
這個Meeting從哪里來?
--nx
5.?re: ClearCase指南-基礎篇(連載一)
clearcase 可以使用clearfsimport -recurse -nsetevent進行批量導入
--china-java.net
閱讀排行榜
1.?weblogic部署方法(11451)
2.?x509數字證書介紹(11432)
3.?一個很不錯的基于角色的權限管理系統設計!(10491)
4.?UML的StereoType的解釋(9049)
5.?When Runtime.exec() won't (5445)
6.?完全卸載Oracle(5406)
7.?OpenLDAP快速指南(5140)
8.?如何發布和查找 WSDL 服務描述(4495)
9.?Eclipse不能自動編譯的問題(4285)
10.?SSL※ X509(3885)
評論排行榜
1.?面試題,做出來3萬月薪(11)
2.?x509數字證書介紹(5)
3.?OpenLDAP快速指南(5)
4.?Compiere的漢化 (5)
5.?oracle的select for update(4)
6.?使用Eclipse plus Pluto開發你的第一個與JSR168兼容的Portlet(3)
7.?迎接RFID的時代(3)
8.?簡化JavaMail:小巧 Jakarta Commons-Email 簡單教程(3)
9.?Visual CHM和jd2chm不錯(2)
10.?Java 遠程方法調用(RMI)(2)
單例模式完全剖析(3)---- 探究簡單卻又使人迷惑的單例模式
http://www.uml.org.cn/j2ee/200501241.htm
單例模式完全剖析(3)---- 探究簡單卻又使人迷惑的單例模式
kevin 翻譯 選自:java研究組織
使用注冊表
使用一個單例類注冊表可以:
在運行期指定單例類
防止產生多個單例類子類的實例
在例8的單例類中,保持了一個通過類名進行注冊的單例類注冊表:
例8 帶注冊表的單例類
import
java.util.
HashMap
;
import
org.apache.log4j.
Logger
;
public
class
Singleton {
private
static
HashMap
map =
new
HashMap
();
private
static
Logger
logger =
Logger
.getRootLogger();
protected
Singleton() {
// Exists only to thwart instantiation
}
public
static
synchronized
Singleton getInstance(
String
classname) {
if
(classname ==
null
)
throw
new
IllegalArgumentException
(
"Illegal classname"
);
Singleton singleton = (Singleton)map.get(classname);
if
(singleton !=
null
) {
logger.info(
"got singleton from map: "
+ singleton);
return
singleton;
}
if
(classname.equals(
"SingeltonSubclass_One"
))
singleton =
new
SingletonSubclass_One();
else
if
(classname.equals(
"SingeltonSubclass_Two"
))
singleton =
new
SingletonSubclass_Two();
map.put(classname, singleton);
logger.info(
"created singleton: "
+ singleton);
return
singleton;
}
// Assume functionality follows that's attractive to inherit
}
這段代碼的基類首先創建出子類的實例,然后把它們存儲在一個Map中。但是基類卻得付出很高的代價因為你必須為每一個子類替換它的getInstance()方法。幸運的是我們可以使用反射處理這個問題。
使用反射
在例9的帶注冊表的單例類中,使用反射來實例化一個特殊的類的對象。與例8相對的是通過這種實現,Singleton.getInstance()方法不需要在每個被實現的子類中重寫了。
例9 使用反射實例化單例類
import
java.util.
HashMap
;
import
org.apache.log4j.
Logger
;
public
class
Singleton {
private
static
HashMap
map =
new
HashMap
();
private
static
Logger
logger =
Logger
.getRootLogger();
protected
Singleton() {
// Exists only to thwart instantiation
}
public
static
synchronized
Singleton getInstance(
String
classname) {
Singleton singleton = (Singleton)map.get(classname);
if
(singleton !=
null
) {
logger.info(
"got singleton from map: "
+ singleton);
return
singleton;
}
try
{
singleton = (Singleton)
Class
.forName(classname).newInstance();
}
catch
(
ClassNotFoundException
cnf) {
logger.fatal(
"Couldn't find class "
+ classname);
}
catch
(
InstantiationException
ie) {
logger.fatal(
"Couldn't instantiate an object of type "
+ classname);
}
catch
(
IllegalAccessException
ia) {
logger.fatal(
"Couldn't access class "
+ classname);
}
map.put(classname, singleton);
logger.info(
"created singleton: "
+ singleton);
return
singleton;
}
}
關于單例類的注冊表應該說明的是:它們應該被封裝在它們自己的類中以便最大限度的進行復用。
封裝注冊表
例10列出了一個單例注冊表類。
例10 一個SingletonRegistry類
import
java.util.
HashMap
;
import
org.apache.log4j.
Logger
;
public
class
SingletonRegistry {
public
static
SingletonRegistry REGISTRY =
new
SingletonRegistry();
private
static
HashMap
map =
new
HashMap
();
private
static
Logger
logger =
Logger
.getRootLogger();
protected
SingletonRegistry() {
// Exists to defeat instantiation
}
public
static
synchronized
Object
getInstance(
String
classname) {
Object
singleton = map.get(classname);
if
(singleton !=
null
) {
return
singleton;
}
try
{
singleton =
Class
.forName(classname).newInstance();
logger.info(
"created singleton: "
+ singleton);
}
catch
(
ClassNotFoundException
cnf) {
logger.fatal(
"Couldn't find class "
+ classname);
}
catch
(
InstantiationException
ie) {
logger.fatal(
"Couldn't instantiate an object of type "
+
classname);
}
catch
(
IllegalAccessException
ia) {
logger.fatal(
"Couldn't access class "
+ classname);
}
map.put(classname, singleton);
return
singleton;
}
}
注意我是把SingletonRegistry類作為一個單例模式實現的。我也通用化了這個注冊表以便它能存儲和取回任何類型的對象。例11顯示了的Singleton類使用了這個注冊表。
例11 使用了一個封裝的注冊表的Singleton類
import
java.util.
HashMap
;
import
org.apache.log4j.
Logger
;
public
class
Singleton {
protected
Singleton() {
// Exists only to thwart instantiation.
}
public
static
Singleton getInstance() {
return
(Singleton)SingletonRegistry.REGISTRY.getInstance(classname);
}
}
上面的Singleton類使用那個注冊表的唯一實例通過類名取得單例對象。
現在我們已經知道如何實現線程安全的單例類和如何使用一個注冊表去在運行期指定單例類名,接著讓我們考查一下如何安排類載入器和處理序列化。
Classloaders
在許多情況下,使用多個類載入器是很普通的--包括servlet容器--所以不管你在實現你的單例類時是多么小心你都最終可以得到多個單例類的實例。如果你想要確保你的單例類只被同一個的類載入器裝入,那你就必須自己指定這個類載入器;例如:
private
static
Class
getClass(
String
classname)
throws
ClassNotFoundException
{
ClassLoader
classLoader =
Thread
.currentThread().getContextClassLoader();
if
(classLoader ==
null
)
classLoader = Singleton.
class
.getClassLoader();
return
(classLoader.loadClass(classname));
}
}
這個方法會嘗試把當前的線程與那個類載入器相關聯;如果classloader為null,這個方法會使用與裝入單例類基類的那個類載入器。這個方法可以用Class.forName()代替。
序列化
如果你序列化一個單例類,然后兩次重構它,那么你就會得到那個單例類的兩個實例,除非你實現readResolve()方法,像下面這樣:
例12 一個可序列化的單例類
import
org.apache.log4j.
Logger
;
public
class
Singleton
implements
java.io.
Serializable
{
public
static
Singleton INSTANCE =
new
Singleton();
protected
Singleton() {
// Exists only to thwart instantiation.
}
[b]
private
Object
readResolve() {
return
INSTANCE;
}[/b]}
上面的單例類實現從readResolve()方法中返回一個唯一的實例;這樣無論Singleton類何時被重構,它都只會返回那個相同的單例類實例。
例13測試了例12的單例類:
例13 測試一個可序列化的單例類
import
java.io.*;
import
org.apache.log4j.
Logger
;
import
junit.framework.
Assert
;
import
junit.framework.
TestCase
;
public
class
SingletonTest
extends
TestCase
{
private
Singleton sone =
null
, stwo =
null
;
private
static
Logger
logger =
Logger
.getRootLogger();
public
SingletonTest(
String
name) {
super
(name);
}
public
void
setUp() {
sone = Singleton.INSTANCE;
stwo = Singleton.INSTANCE;
}
public
void
testSerialize() {
logger.info(
"testing singleton serialization..."
);
[b] writeSingleton();
Singleton s1 = readSingleton();
Singleton s2 = readSingleton();
Assert
.assertEquals(
true
, s1 == s2);[/b] }
private
void
writeSingleton() {
try
{
FileOutputStream
fos =
new
FileOutputStream
(
"serializedSingleton"
);
ObjectOutputStream
oos =
new
ObjectOutputStream
(fos);
Singleton s = Singleton.INSTANCE;
oos.writeObject(Singleton.INSTANCE);
oos.flush();
}
catch
(
NotSerializableException
se) {
logger.fatal(
"Not Serializable Exception: "
+ se.getMessage());
}
catch
(
IOException
iox) {
logger.fatal(
"IO Exception: "
+ iox.getMessage());
}
}
private
Singleton readSingleton() {
Singleton s =
null
;
try
{
FileInputStream
fis =
new
FileInputStream
(
"serializedSingleton"
);
ObjectInputStream
ois =
new
ObjectInputStream
(fis);
s = (Singleton)ois.readObject();
}
catch
(
ClassNotFoundException
cnf) {
logger.fatal(
"Class Not Found Exception: "
+ cnf.getMessage());
}
catch
(
NotSerializableException
se) {
logger.fatal(
"Not Serializable Exception: "
+ se.getMessage());
}
catch
(
IOException
iox) {
logger.fatal(
"IO Exception: "
+ iox.getMessage());
}
return
s;
}
public
void
testUnique() {
logger.info(
"testing singleton uniqueness..."
);
Singleton another =
new
Singleton();
logger.info(
"checking singletons for equality"
);
Assert
.assertEquals(
true
, sone == stwo);
}
}
前面這個測試案例序列化例12中的單例類,并且兩次重構它。然后這個測試案例檢查看是否被重構的單例類實例是同一個對象。下面是測試案例的輸出:
Buildfile: build.xml
init:
[echo] Build 20030422 (22-04-2003 11:32)
compile:
run-test-text:
[java] .INFO main: testing singleton serialization...
[java] .INFO main: testing singleton uniqueness...
[java] INFO main: checking singletons
for
equality
[java]
Time
: 0.1
[java] OK (2 tests)
單例模式結束語
單例模式簡單卻容易讓人迷惑,特別是對于Java的開發者來說。在這篇文章中,作者演示了Java開發者在顧及多線程、類載入器和序列化情況如何實現單例模式。作者也展示了你怎樣才能實現一個單例類的注冊表,以便能夠在運行期指定單例類。
posted on 2005-04-18 14:33
笨笨
閱讀(332)
評論(0)
編輯
收藏
所屬分類:
J2EE
、
ALL
、
J2SE
新用戶注冊
刷新評論列表
只有注冊用戶
登錄
后才能發表評論。
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
相關文章:
簡化JavaMail:小巧 Jakarta Commons-Email 簡單教程
讀"Under the Hood of J2EE Clustering" J2EE集群
Phase
x509數字證書介紹
SSL※ X509
了解安全性斷言標記語言
架構藍圖--軟件架構 "4+1" 視圖模型
主動對象
Profile,Stereotype,TaggedValue與OCL漫談
Drools 為你的業務邏輯提供框架(翻譯)
Powered by:
BlogJava
Copyright © 笨笨
主站蜘蛛池模板:
eeuss影院免费92242部
|
18禁在线无遮挡免费观看网站
|
亚洲日本va一区二区三区
|
污视频网站在线免费看
|
1000部拍拍拍18勿入免费视频下载
|
我要看免费的毛片
|
国产A在亚洲线播放
|
风间由美在线亚洲一区
|
最近免费中文在线视频
|
亚洲毛片在线免费观看
|
baoyu122.永久免费视频
|
美女黄网站人色视频免费国产
|
香蕉视频在线观看亚洲
|
一个人看的免费观看日本视频www 一个人看的免费视频www在线高清动漫
|
色天使亚洲综合在线观看
|
成人免费乱码大片A毛片
|
在线观看人成网站深夜免费
|
久久青青草原亚洲AV无码麻豆
|
日本在线观看免费高清
|
中文字幕中韩乱码亚洲大片
|
猫咪免费人成在线网站
|
最近免费最新高清中文字幕韩国
|
亚洲无码视频在线
|
久久久久久久久无码精品亚洲日韩
|
国产免费一区二区三区VR
|
久久精品国产亚洲αv忘忧草
|
免费人妻无码不卡中文字幕系
|
99久久99热精品免费观看国产
|
亚洲福利电影在线观看
|
日韩免费一区二区三区
|
亚洲日本久久一区二区va
|
最近中文字幕无免费
|
亚洲日韩中文字幕无码一区
|
亚洲国产专区一区
|
免费无码国产在线观国内自拍中文字幕
|
国产91精品一区二区麻豆亚洲
|
毛片无码免费无码播放
|
亚洲国产高清国产拍精品
|
啦啦啦高清视频在线观看免费
|
亚洲国产精品综合久久网各
|
曰曰鲁夜夜免费播放视频
|