Singleton模式
但是static通常會給你造成一些障礙
該篇並沒有涉及到
讓我們先來寫個簡單的SqlHelper吧
using System;
using System
using System
namespace APeng
{
public class SqlHelper
{
private string m_connString =
//Sql數據庫連接字符串
public SqlDataReader ExecuteReader(CommandType cmdType
SqlCommand cmd = new SqlCommand();
SqlConnection conn = new SqlConnection(m_connString);
try
{
PrepareCommand(cmd
SqlDataReader rdr = cmd
cmd
return rdr;
}
catch (Exception ex)
{
conn
conn
throw ex;
}
}
private void PrepareCommand(SqlCommand cmd
{
if (conn
conn
cmd
cmd
cmd
if (cmdParms != null)
{
foreach (SqlParameter parm in cmdParms)
cmd
}
}
}
}
這段代碼大家應該很熟悉了
using System;
using System
using System
namespace APeng
{
class Program
{
static void Main(string[] args)
{
SqlHelper helper = new SqlHelper();
string cmdText =
using (SqlDataReader reader = helper
{
while (reader
{
Console
Console
}
}
Console
}
}
}
程序正常輸出: 編號:
很簡單
接下來我們將要優化這個SqlHelper
一) 將SqlHelper中的private string m_connString =
這個修改是否有必要呢? (如果沒能給我帶來什麼好處
小菜先在A地方實例化一個SqlHelper
SqlHelper helper
那麼會有如下構造過程:
(如果是值類型如int
(那麼現在空間存儲數據為
小菜然後在B地方又實例化一個SqlHelper
SqlHelper helper
那麼會有如下構造過程:
(那麼現在空間存儲數據為
噢
而且老是把m_connString空間存儲數據置為相同的
該死的
唉
等等
那它能改變這種狀況嗎?
小菜先在A地方實例化一個SqlHelper
SqlHelper helper
那麼會有如下構造過程:
(如果是值類型如int
(那麼現在空間存儲數據為
小菜然後在B地方又實例化一個SqlHelper
SqlHelper helper
那麼會有如下構造過程:
看來真不錯
看來多虧了static
注意:這裡應該引起你的關注
有一些朋友的代碼中時常出現為值類型成員賦
public class Person//人類
{
private int _age =
}
或者
public class Person//人類
{
private Address _address = null;//地址對象
}
這其實是無必要的
Effective C# 中有介紹
其實上面主要的知識點是對象的構造過程
第一種:
1.當我們調用類裡的靜態方法時
2.為靜態成員分配內存空間
3.執行靜態成員的初始化語句(也就是賦值語句)
4.執行類的靜態構造函數
很明顯
1.當我們對類實例化的時候
2.為靜態成員分配內存空間
3.執行靜態成員的初始化語句(也就是賦值語句)
4.執行類的靜態構造函數
5
6.執行普通成員的初始化語句(也就是賦值語句)
很明顯
二) 將public SqlDataReader ExecuteReader() 修改成 public static SqlDataReader ExecuteReader()
修改不修改關鍵看什麼呢?
如果該方法無需保持或變動跟對象有關的狀態
我們的ExecuteReader()滿足上面條件
三) 將public class SqlHelper 修改為 public static class SqlHelper
經過上面的修改後
可是沒有public abstract sealed class SqlHelper 但有static
Math類相信大家都用的很爽吧
很明顯Math也是做為一個工具類
注意:有些朋友要說了
可以
有些朋友要說了
接下來就正式來說單件模式吧! (只允許實例化一次)
public sealed class Singleton
{
private static readonly Singleton _instance = new Singleton();
private Singleton()
{ }
public static Singleton Instance
{
get
{
return _instance;
}
}
public void DoSomething()
{
Console
}
}
接下來
static void Main(string[] args)
{
Singleton s
Singleton s
s
s
Console
}
恩
其一: 如果很看注性能的話
但通常上面的代碼是夠用的
其二: 由於靜態成員的初始化時間很難控制
這裡就用到了前面講到的對象構造順序
這也是Effective C#中有介紹
所以代碼修改為
public sealed class Singleton
{
private static readonly Singleton _instance;
private Singleton()
{ }
static Singleton()
{
_instance = Singleton();
}
public static Singleton Instance
{
get
{
return _instance;
}
}
public void DoSomething()
{
Console
}
}
如果對性能不是太講究的話
二)第二種單件模式lazy
代碼也很清晰
為什麼呢?
線程
線程
進入執行第
線程
obj
這樣的話
那就進入第三種單件模式
三)第三種單件模式
public sealed class Singleton
{
private static Singleton _instance;
private static object _lockHelper = new object();
private Singleton()
{ }
public static Singleton Instance
{
get
{
lock (_lockHelper)
{
if (_instance == null)
{
_instance = new Singleton();
}
}
return _instance;
}
}
public void DoSomething()
{
Console
}
}
看來該單件模式支持多線程
如果_instance已經被初始化
我們只需要第一次初始化的時候同步
看來double
那就進入第四種單件模式
四)第四種單件模式
public sealed class Singleton
{
private static Singleton _instance;
private static object _lockHelper = new object();
private Singleton()
{ }
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (_lockHelper)
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
public void DoSomething()
{
Console
}
}
記得看到過有人這麼問
那我們來分析一下
線程
線程
線程
線程
現在又是雙件了
這個單件模式被用的最多
因為上面的代碼被編譯
所以在多線程中可能還是會出狀況
那就來看第五種單件模式
五)第五種單件模式
public sealed class Singleton
{
private static volatile Singleton _instance;
private static object _lockHelper = new object();
private Singleton()
{ }
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (_lockHelper)
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
public void DoSomething()
{
Console
}
}
小菜並沒有做多少事
volatile關鍵字有這麼大魔力? 對
編譯器保證對此_instance的讀寫操作都不會被優化
接下來我們來講個集萬千寵愛與一生的單件模式
六)第六個單件模式
public sealed class Singleton
{
private Singleton()
{ }
public static Singleton Instance
{
get
{
return Nested
}
}
public void DoSomething()
{
Console
}
//嵌套類
private class Nested
{
internal static readonly Singleton instance;
private Nested()
{ }
static Nested()
{
instance = new Singleton();
}
}
}
return Nested
第一次執行它時
很明顯用到的知識還是前面的對象構造順序
到這裡單件模式的多種實現都介紹完了
From:http://tw.wingwit.com/Article/program/net/201311/12086.html