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部署方法(11453)
2.?x509數字證書介紹(11432)
3.?一個很不錯的基于角色的權限管理系統設計!(10492)
4.?UML的StereoType的解釋(9052)
5.?When Runtime.exec() won't (5445)
6.?完全卸載Oracle(5408)
7.?OpenLDAP快速指南(5140)
8.?如何發布和查找 WSDL 服務描述(4496)
9.?Eclipse不能自動編譯的問題(4286)
10.?SSL※ X509(3888)
評論排行榜
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 © 笨笨
主站蜘蛛池模板:
免费看香港一级毛片
|
最近中文字幕无吗高清免费视频
|
日韩色视频一区二区三区亚洲
|
亚洲男人的天堂网站
|
国产精品亚洲lv粉色
|
毛片a级三毛片免费播放
|
亚洲最大的成人网站
|
两性色午夜视频免费播放
|
久久国产免费观看精品3
|
99久久这里只精品国产免费
|
a毛片全部播放免费视频完整18
|
**实干一级毛片aa免费
|
免费国产高清视频
|
亚洲乱码卡一卡二卡三
|
大片免费观看92在线视频线视频
|
91热成人精品国产免费
|
成人午夜亚洲精品无码网站
|
亚洲一区精彩视频
|
国产免费网站看v片在线
|
四虎成人精品一区二区免费网站
|
亚洲日韩精品无码专区网址
|
亚洲中文无码永久免
|
国产成人免费福利网站
|
亚洲色图综合网站
|
国产精品免费久久久久电影网
|
久久不见久久见免费影院
|
午夜亚洲国产理论秋霞
|
九一在线完整视频免费观看
|
好男人看视频免费2019中文
|
男人免费视频一区二区在线观看
|
啦啦啦手机完整免费高清观看
|
国产偷国产偷亚洲高清人
|
最新69国产成人精品免费视频动漫
|
狼色精品人妻在线视频免费
|
国产精品酒店视频免费看
|
中文字幕不卡免费视频
|
亚洲综合丁香婷婷六月香
|
va亚洲va日韩不卡在线观看
|
最新亚洲卡一卡二卡三新区
|
国产精品久久久久久久久久免费
|
野花视频在线官网免费1
|