您好,登錄后才能下訂單哦!
單例模式的目的就是要控制特定的類只產生一個對象,當然也允許在一定情況下靈活的改變對象的個數。
怎么來實現單例模式呢?
一個類的對象的產生是由類構造函數來完成的,如果想限制對象的產生,一個辦法就是:
1,將構造函數變為私有的(至少是受保護的),使得外面的類不能通過引用來產生對象;
2,同時為了保證類的可用性,就必須提供一個自己的對象以及訪問這個對象的靜態方法。
單例模式可分為有狀態的和無狀態的。
有狀態的單例對象一般也是可變的單例對象,多個單態對象在一起就可以作為一個狀態倉庫一樣向外提供服務。
沒有狀態的單例對象也就是不變單例對象,僅用做提供工具函數。
UML類圖:
實現:
java:
一、餓漢式:
singleton1.java:
/*
* 創建人:顏超
* 創建時間:2013-6-26
* 文件名:singleton1.java
* 創建型設計模式
* 單例(singleton)
* 餓漢式
*/
public class Singleton1 {
//在自己內部定義自己一個實例
//注意這是private 只供內部調用
private static Singleton1 instance = new Singleton1();
//將構造函數設置為私有
private Singleton1(){
System.out.println("new an instance!");
}
//靜態工廠方法,提供了一個供外部訪問得到對象的靜態方法
public static Singleton1 getInstance(){
return instance;
}
public static void main(String[] args) {
Singleton1.getInstance();
}
}
二、懶漢式:
singleton2.java:
/*
* 創建人:顏超
* 創建時間:2013-6-26
* 文件名:singleton2.java
* 創建型設計模式
* 單例(singleton)
* 懶漢式
*/
public class Singleton2 {
private static Singleton2 instance = null;
private Singleton2(){
System.out.println("new an instance!");
}
//對靜態工廠方法進行了同步處理,原因很明顯——為了防止多線程環境中產生多個實例
//將類對自己的實例化延遲到第一次被引用的時候。而在"餓漢式"則是在類被加載的時候實例化,這樣多次加載會造成多次實例化
public static synchronized Singleton2 getInstance(){
if (instance == null){
instance = new Singleton2();
}
return instance;
}
public static void main(String[] args) {
// Singleton1 s1 = new Singleton1();
Singleton2.getInstance();
}
}
三、
以上兩種實現方式均失去了多態性,不允許被繼承。還有另外一種靈活點的實現,將構造函數設置為受保護的,這樣允許被繼承產生子類。
singleton3.java:
import java.util.HashMap;
public class Singleton3 {
private static HashMap sinRegistry = new HashMap();
private static Singleton3 instance = new Singleton3();
protected Singleton3(){
System.out.println("Construction for Singleton3!");
}
public static Singleton3 getInstance(String name){
if (name == null){
name = "Singleton3";
}
if (sinRegistry.get(name) == null){
try{
sinRegistry.put(name, Class.forName(name).newInstance());
}catch(Exception e){
e.printStackTrace();
}
}
return (Singleton3)(sinRegistry.get(name));
}
public void test(){
System.out.println("get Class Success!");
}
}
class Singleton3Child1 extends Singleton3 {
public Singleton3Child1(){
System.out.println("Construction for Singleton3Child1!");
}
public static Singleton3Child1 getInstance(){
return (Singleton3Child1)Singleton3.getInstance("Singleton3Child1");
}
public void test(){
System.out.println("get Child1 Class Success!");
}
}
class Singleton3Child2 extends Singleton3 {
public Singleton3Child2(){
System.out.println("Construction for Singleton3Child2!");
}
public static Singleton3Child2 getInstance(){
return (Singleton3Child2)Singleton3.getInstance("Singleton3Child2");
}
public void test(){
System.out.println("get Child2 Class Success!");
}
}
testMain.java:
public class testMain {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("#########################");
Singleton3Child1 s3c1 = new Singleton3Child1();
Singleton3Child2 s3c2 = new Singleton3Child2();
// 因為hashmap的key值是唯一的,所以,下面的三部分一次只能顯示一部分
System.out.println("#########################");
Singleton3Child1.getInstance(); //add Singleton3Child1 into hashmap
Singleton3Child2.getInstance(); //add Singleton3Child2 into hashmap
System.out.println("#########################");
Singleton3.getInstance("Singleton3Child1"); //add Singleton3Child1 into hashmap
Singleton3.getInstance("Singleton3Child2"); //add Singleton3Child2 into hashmap
System.out.println("#########################");
Singleton3Child1.getInstance("Singleton3Child1"); //add Singleton3Child1 into hashmap
Singleton3Child1.getInstance("Singleton3Child2"); //add Singleton3Child2 into hashmap
Singleton3Child2.getInstance("Singleton3Child1"); //add Singleton3Child1 into hashmap
Singleton3Child2.getInstance("Singleton3Child2"); //add Singleton3Child2 into hashmap
}
}
由于在 java 中子類的構造函數的范圍不能比父類的小,所以可能存在不守規則的客戶
程序使用其構造函數來產生實例,造成單例模式失效。
C++:
Singleton.cpp:
#include <iostream>
using namespace std;
class Singleton{
public:
static Singleton* getInstance(){
if(instance == NULL){
cout << "There is no instance!!!" << endl;
instance = new Singleton();
}
return instance;
}
private:
Singleton(){
cout << "new an instance!!!" << endl;
}
static Singleton* instance;
};
// static variable "instance" can not initialized in class
Singleton* Singleton::instance = NULL;
int main() {
Singleton::getInstance();
return 0;
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。