java 单例设计_Java 之单例设计模式
設(shè)計(jì)模式: 對(duì)問(wèn)題行之有效的解決方式, 其實(shí)它是一種思想.
單例設(shè)計(jì)模式
解決的問(wèn)題:就是可以保證一個(gè)類在內(nèi)存中的對(duì)象唯一性. 即單個(gè)實(shí)例.
比如對(duì)于A 和 B 兩個(gè)程序使用同一個(gè)配置信息對(duì)象時(shí), A 對(duì)配置信息作出修改, B 也與之對(duì)應(yīng)的更新配置信息, 即需要保證該對(duì)象的唯一性.
如何保證對(duì)象唯一性呢?
不允許其他程序用 new 創(chuàng)建該類對(duì)象
在該類中創(chuàng)建一個(gè)本類實(shí)例
對(duì)外提供一個(gè)方法讓其他程序可以獲取該對(duì)象.
步驟:
私有化該類構(gòu)造函數(shù)
通過(guò) new 在本類中創(chuàng)建一個(gè)本類對(duì)象
定義一個(gè)公有方法, 將創(chuàng)建的對(duì)象返回
兩種方式
餓漢式: 類一加載, 對(duì)象就存在了.
懶漢式: 類加載進(jìn)來(lái), 沒有對(duì)象, 只有調(diào)用 getInstance 方法時(shí), 才會(huì)創(chuàng)建對(duì)象.
也稱為 單例設(shè)計(jì)模式的延遲加載模式. 但是, 懶漢式在多線程訪問(wèn)時(shí),存在安全隱患.
// 第一種方式: 餓漢式
class Single
{
Single s = new Single(); // 在本類中創(chuàng)建一個(gè)本類對(duì)象
private Single(){} // 私有化該類構(gòu)造函數(shù)
// 定義一個(gè)公有方法, 將創(chuàng)建的對(duì)象返回. 用于返回對(duì)象 s, 所以返回類型 Single
public Single getInstance()
{
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single ss = Single.getInstance();
}
}
/*
分析一: main 函數(shù)中, getInstance 方法調(diào)用不能使用對(duì)象調(diào)用, 只能使用類名調(diào)用.
所以 Single 類中該方法需要使用 static 修飾.
分析二: getInstance 方法為靜態(tài)方法, 它訪問(wèn)的內(nèi)容必須是靜態(tài)的,所以對(duì)象 s 也需要靜態(tài)修飾.
*/
// 改進(jìn)
class Single
{
private static Single s = new Single();
private Single(){}
public static Single getInstance() // 提供該方法訪問(wèn)實(shí)例對(duì)象 s, 是為了對(duì)象的可控
{
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single ss = Single.getInstance();
}
}
// 第二種方式: 懶漢式
// 類加載進(jìn)來(lái), 沒有對(duì)象, 只有調(diào)用 getInstance 方法時(shí), 才會(huì)創(chuàng)建對(duì)象.
class Single2
{
private static Single2 s = null;
private Single(){}
public static Single2 getInstance()
{
if(s==null)
s = new Single2();
return s;
}
}
// 示例:下列代碼的輸出結(jié)果
class SingleDemo
{
public static void main(String[] args)
{
Test t1 = Test.getInstance();
Test t2 = Test.getInstance();
t1.setNum(10);
t2.setNum(20);
System.out.println(t1.getNum()); // 輸出 20
System.out.println(t2.getNum()); // 輸出 20
}
}
class Test
{
private int num;
private static Test t = new Test();
private Test(){}
public static Test getInstance()
{
return t;
}
public void setNum(int num)
{
this.num = num;
}
public int getNum()
{
return num;
}
}
// 懶漢式二:避免多線程同時(shí)調(diào)用getInstance()方法, 可以使用關(guān)鍵字synchronized
class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){}
public synchronized static LazySingleton getInstance() {
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
// 懶漢式三:為提高系統(tǒng)性能,對(duì)"instance = new LazySingleton()"進(jìn)行鎖定
class LazySingleton{
private static LazySingleton instance = null;
private LazySingleton(){}
public static LazySingleton getInstance(){
if(instance == null){ // 此處,有可能造成單例對(duì)象不唯一
synchronized(LazySingleton.class){
instance = new LazySingleton();
}
}
return instance;
}
}
// 懶漢式四:雙重檢查鎖定(Double-Check Locking)
class LazySingleton{
// 注意,此處增加修飾符 volatile
private volatile static LazySingleton instance = null;
private LazySingleton(){}
public static LazySingleton getInstance(){
// 第一重判斷
if(instance == null){
// 鎖定代碼塊
synchronized(LazySingleton.class){
// 第二重判斷
if(instance == null){
instance = new LazySingleton();
}
}
}
return instance;
}
}
//單例第三種方式: Initialization Demand Holder(IoDH)技術(shù)
// 在單例類中增加一個(gè)靜態(tài)(static)內(nèi)部類
class Singleton{
private Singleton(){}
// 靜態(tài)類
private static class HolderClass {
private final static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return HolderClass.instance;
}
public static void main(String args[]){
Singleton s1, s2;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();
System.out.println(s1 == s2);
}
}
_參考資料_
- [JavaSE 基礎(chǔ)視頻(畢向東)](https://www.bilibili.com/video/av3092292/#page=4)
- [單例模式中的雙重檢查](http://blog.csdn.net/chenchaofuck1/article/details/51702129)
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的java 单例设计_Java 之单例设计模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 去除敏感词
- 下一篇: java核心-多线程-Java多线程编程