這篇文章主要介紹了java 單例模式的實例詳解的相關資料,希望透過本文能幫助大家徹底理解掌握這部分內容,需要的朋友可以參考下
java 單範例模式的實例詳解
概念:
java中單例模式是一種常見的設計模式,單例模式分為三種:懶漢式單例、餓漢式單例、登記式單例三種。
單例模式有一下特點:
# 1、單例類別只能有一個實例。
2、單例類別必須自己創建自己的唯一實例。
3、單例類別必須提供此實例給所有其他物件。
單例模式確保某個類別只有一個實例,並且自行實例化並向整個系統提供這個實例。在電腦系統中,執行緒池、快取、日誌物件、對話方塊、印表機、顯示卡的驅動程式物件常被設計成單例。這些應用都或多或少具有資源管理器的功能。每台電腦可以有若干台印表機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到印表機。每台電腦可以有若干通信端口,系統應集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調用。總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。
先看一個經典的單例實作。
public class Singleton { private static Singleton uniqueInstance = null; private Singleton() { // Exists only to defeat instantiation. } public static Singleton getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } // Other methods... }
Singleton透過將建構方法限定為private避免了類別在外部被實例化,在同一個虛擬機器範圍內,Singleton的唯一實例只能透過getInstance( )方法訪問。 (事實上,透過Java反射機制是能夠實例化構造方法為private的類別的,那基本上會使所有的Java單例實現失效。此問題在此處不做討論,姑且掩耳盜鈴地認為反射機制不存在。所謂線程安全是指:如果你的程式碼所在的進程中有多個執行緒同時運行,而這些執行緒可能會同時運行這段程式碼。如果每次運行結果和單執行緒運行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。或者說:一個類別或程式所提供的介面對於執行緒來說是原子操作或是多個執行緒之間的切換不會導致該介面的執行結果存在二義性,也就是說我們不用考慮同步的問題。顯然以上實作並不符合執行緒安全的要求,在並發環境下很可能出現多個Singleton實例。
public class TestStream { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } //该类只能有一个实例 private TestStream(){} //私有无参构造方法 //该类必须自行创建 //有2种方式 /*private static final TestStream ts=new TestStream();*/ private static TestStream ts1=null; //这个类必须自动向整个系统提供这个实例对象 public static TestStream getTest(){ if(ts1==null){ ts1=new TestStream(); } return ts1; } public void getInfo(){ System.out.println("output message "+name); } } /** * */ public class TestMain { public static void main(String [] args){ TestStream s=TestStream.getTest(); s.setName("张孝祥"); System.out.println(s.getName()); TestStream s1=TestStream.getTest(); s1.setName("张孝祥"); System.out.println(s1.getName()); s.getInfo(); s1.getInfo(); if(s==s1){ System.out.println("创建的是同一个实例"); }else if(s!=s1){ System.out.println("创建的不是同一个实例"); }else{ System.out.println("application error"); } } }
张孝祥 张孝祥 output message 张孝祥 output message 张孝祥 创建的是同一个实例
:由結果可以得知單例模式為一個物件導向的應用程式提供了物件惟一的存取點,不管它實現何種功能,整個應用程式都會同享一個實例物件。
1.餓漢式單例類別#
//饿汉式单例类.在类初始化时,已经自行实例化 public class Singleton1 { //私有的默认构造子 private Singleton1() {} //已经自行实例化 private static final Singleton1 single = new Singleton1(); //静态工厂方法 public static Singleton1 getInstance() { return single; } }
//懒汉式单例类.在第一次调用的时候实例化 public class Singleton2 { //私有的默认构造子 private Singleton2() {} //注意,这里没有final private static Singleton2 single=null; //静态工厂方法 public synchronized static Singleton2 getInstance() { if (single == null) { single = new Singleton2(); } return single; } }
#
import java.util.HashMap; import java.util.Map; //登记式单例类. //类似Spring里面的方法,将类名注册,下次从里面直接获取。 public class Singleton3 { private static Map<String,Singleton3> map = new HashMap<String,Singleton3>(); static{ Singleton3 single = new Singleton3(); map.put(single.getClass().getName(), single); } //保护的默认构造子 protected Singleton3(){} //静态工厂方法,返还此类惟一的实例 public static Singleton3 getInstance(String name) { if(name == null) { name = Singleton3.class.getName(); System.out.println("name == null"+"--->name="+name); } if(map.get(name) == null) { try { map.put(name, (Singleton3) Class.forName(name).newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return map.get(name); } //一个示意性的商业方法 public String about() { return "Hello, I am RegSingleton."; } public static void main(String[] args) { Singleton3 single3 = Singleton3.getInstance(null); System.out.println(single3.about()); } }
以上是Java單例模式的實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!