技術交流,DH講解.
單例模式一般都是在全域變數區存放一個變數,然後在建立的時候先看這個全域變數是否被賦值了,
如果沒有就建立如果有就直接返回這個全域變數.
UML圖:
要是不想被人建立對象的執行個體,那麼一般的辦法就是把構造方法設定成私人域.
好了,原理說了,我們就來看看代碼怎麼實現吧.
1 <?php
2 class PHPSinglton {
3 private $huangjacky;
4 private static $singleinstance;
5 private function __construct(){
6 $huangjacky='TheFiend';
7 }
8 static function GetInstance(){
9 if(!isset($singleinstance))
10 $singleinstance = new PHPSinglton();
11 return $singleinstance;
12 }
13 }
14 ?>
這個是PHP的單例模式的代碼. 我們用一個靜態變數來充當了全域變數.
接下來是C#的例子:
1 public class CSharpSingleton{
2 private static CSharpSingleton instance;
3 private CSharpSingleton(){
4 }
5 public static CSharpSingleton GetInstance(){
6 if (instance == null)
7 instance = new CSharpSingleton();
8 return instance;
9 }
10 }
11 private void button1_Click(object sender, EventArgs e)
12 {
13 CSharpSingleton a, b;
14 //a = new CSharpSingleton();這個會報錯的
15 a = CSharpSingleton.GetInstance();
16 b = CSharpSingleton.GetInstance();
17 if (a==b)
18 { MessageBox.Show("Equals"); }
19 }
20
現在PHP和C#的代碼都有了.
我們該幹什麼了?嘿嘿,肯定是用我們喜歡的Delphi來實現一下:
由於Delphi裡面如果我們將Constructor設定成private但是Delphi會悄悄的改回public
而且我們還發現不了...
有問題就要解決問題咯.看看
TSingleton = Class
Private
Class Var Instance: TSingleton;
Public
Class Function GetInstance: TSingleton;
Class Function NewInstance: TObject; Override;
Procedure FreeInstance; Override;
End;
我們會發現這裡重載了TObject裡面的2個方法.
Procedure TSingleton.FreeInstance;
Begin
Inherited;
Instance := Nil;
End;
Class Function TSingleton.GetInstance: TSingleton;
Begin
If Not Assigned( Instance ) Then
Instance := TSingleton.Create;
Result := Instance;
End;
Class Function TSingleton.NewInstance: TObject;
Begin
If Not Assigned( Instance ) Then
Instance := TSingleton( Inherited NewInstance );
Result := Instance;
End;
其實也是在這裡判斷靜態變數是否建立了.
測試一下:
Procedure TForm2.Button1Click( Sender: TObject );
Var
A, B: TSingleton;
Begin
A := TSingleton.Create;
B := TSingleton.Create;
ShowMessageFmt( 'a:%8x,b:%8x', [ Integer( A ), Integer( B ) ] );
End;
我們可以看見Create後的A,B 以及GetInstance後的對象地址都是一樣的.
我們可以看到Delphi要實現單例模式就是靠重載NewInstance方法,因為我們在前面文章看見,對象的構造過程中CreateInstance是最重要的一步.
適用性:
- 當類只能有一個執行個體而且客戶可以從一個眾所周知的訪問點訪問它時。
- 當這個唯一執行個體應該是通過子類化可擴充的,並且客戶應該無需更改代碼就能使用一個擴充的執行個體時。
好的今天就說到這裡,我是DH.