**在有些系統中,為了節省內存資源、保證數據內容的一致性,對某些類要求只能創建一個實例,這就是所謂的單例模式。**
## 單例模式的定義與特點
單例(Singleton)模式的定義:指一個類只有一個實例,且該類能自行創建這個實例的一種模式。例如,Windows 中只能打開一個任務管理器,這樣可以避免因打開多個任務管理器窗口而造成內存資源的浪費,或出現各個窗口顯示內容的不一致等錯誤。
在計算機系統中,還有 Windows 的回收站、操作系統中的文件系統、多線程中的線程池、顯卡的驅動程序對象、打印機的后臺處理服務、應用程序的日志對象、數據庫的連接池、網站的計數器、Web 應用的配置對象、應用程序中的對話框、系統中的緩存等常常被設計成單例。
單例模式在現實生活中的應用也非常廣泛,例如公司 CEO、部門經理等都屬于單例模型。J2EE 標準中的[Servlet](http://c.biancheng.net/servlet/)Context 和 ServletContextConfig、[Spring](http://c.biancheng.net/spring/)框架應用中的 ApplicationContext、數據庫中的連接池等也都是單例模式。
單例模式有 3 個特點:
1. 單例類只有一個實例對象;
2. 該單例對象必須由單例類自行創建;
3. 單例類對外提供一個訪問該單例的全局訪問點。
## 單例模式的優點和缺點
單例模式的優點:
* 單例模式可以保證內存里只有一個實例,減少了內存的開銷。
* 可以避免對資源的多重占用。
* 單例模式設置全局訪問點,可以優化和共享資源的訪問。
單例模式的缺點:
* 單例模式一般沒有接口,擴展困難。如果要擴展,則除了修改原來的代碼,沒有第二種途徑,違背開閉原則。
* 在并發測試中,單例模式不利于代碼調試。在調試過程中,如果單例中的代碼沒有執行完,也不能模擬生成一個新的對象。
* 單例模式的功能代碼通常寫在一個類中,如果功能設計不合理,則很容易違背單一職責原則。
* 單列模式在業務代碼中加入和業務無關的代碼
> 單例模式看起來非常簡單,實現起來也非常簡單。單例模式在面試中是一個高頻面試題。希望大家能夠認真學習,掌握單例模式,提升核心競爭力,給面試加分,順利拿到 Offer。
單例模式應用的場景一般發現在以下條件下:
(1)資源共享的情況下,避免由于資源操作時導致的性能或損耗等。如上述中的日志文件,應用配置。
(2)控制資源的情況下,方便資源之間的互相通信。如線程池等。
## 單例模式的結構與實現
單例模式是[設計模式](http://c.biancheng.net/design_pattern/)中最簡單的模式之一。通常,普通類的構造函數是公有的,外部類可以通過“new 構造函數()”來生成多個實例。但是,如果將類的構造函數設為私有的,外部類就無法調用該構造函數,也就無法生成多個實例。這時該類自身必須定義一個靜態私有實例,并向外提供一個靜態的公有函數用于創建或獲取該靜態私有實例。
```
/**
* @purpose: 創建一個單例類
* Class Single
*/
class Single {
/**
* @var Object 保存類實例的靜態成員變量
*/
private static $_instance;
/**
* Single constructor. 私有的構造方法
*/
private function __construct(){
echo 'This is a Constructed method;';
}
/**
* @purpose: 創建__clone方法防止對象被復制克隆
*/
public function __clone(){
//E_USER_ERROR只能通過trigger_error($msg, E_USER_ERROR)手動觸發。E_USER_ERROR是用戶自定義錯誤類型,可以被set_error_handler錯誤處理函數捕獲,允許程序繼續運行。E_ERROR是系統錯誤,不能被set_error_handler錯誤處理函數捕獲,程序會退出運行
trigger_error('Clone is not allow!',E_USER_ERROR);
}
/**
* @return Single|Object 單例方法,用于訪問實例的公共的靜態方法
*/
public static function getInstance(){
if(!(self::$_instance instanceof self)){
self::$_instance = new self;
}
return self::$_instance;
}
/**
* @purpose: 測試方法
*/
public function test(){
echo '調用方法成功';
}
}
```
- 序言
- 從業感悟
- 常用名詞
- HTML
- JS
- ES6新特性
- jquery和vue對比
- 徹底理解this
- JQuery添加自定義函數
- js的實現
- 原始值和引用值
- MYSQL
- 簡介
- 術語
- 特點
- 范式
- 數據類型1
- 數據類型2
- 編碼
- 權限管理
- 事務
- mvvc
- 引擎
- MyISAM與InnoDB區別
- 索引類型
- 鎖
- 死鎖
- 分層架構
- 執行計劃
- join原理
- 高可用
- 日志類型
- 分庫分表
- 中間件
- 服務器
- 操作系統
- 信號量 鎖 隊列
- PHP
- composer加載原理
- composer基礎知識
- 自動加載函數
- composer加載代碼
- composer 自動加載
- 內存管理
- PHP執行流程
- cgi,fastCgi,php-fpm
- HTTP
- 錯誤碼
- 跨域請求
- 面試
- 安全
- HTTP劫持
- 設計模式
- 如何正確的使用設計模式
- 單例模式
- 原型模式
- 簡單工廠模式
- 工廠方法模式
- 抽象工廠模式
- 建造者模式
- 設計原則
- 算法
- PHP短標簽