1. 程式人生 > 其它 >C#OOP CH04 深入類的方法

C#OOP CH04 深入類的方法

技術標籤:c#

C#OOP CH04 深入類的方法

本章目標:

  • 理解並會編寫類的建構函式
  • 會實現方法過載
  • 理解類之間的通訊

1. 建構函式

建構函式是類中一種特殊的方法,也叫構造方法,或者構造器,或者構造體,函式名與類名相同,不返回任何值,也不能用void修飾,主要完成物件的初始化工作。

建構函式在每次例項化類時 通過new關鍵字呼叫

1.1 無參建構函式:

預設情況下,系統會分配給類分配一個無參建構函式,並且沒有方法體,用來對成員變數進行初始化操作。

可以自定義一個無參建構函式,在方法體內對類的屬性進行初始化操作。

無參建構函式的語法為:

訪問修飾符  類名()
{
	//方法體
}

1.2 帶參建構函式:

語法為: 引數列表一般用來給類的屬性賦值.

訪問修飾符  類名(引數列表)
{
	//方法體
}     

注意:

  • 當我們建立一個類時,系統將自動給類分配一個預設的無參建構函式

    而一旦定義了建構函式 系統將不再自動分配建構函式。

    結構與列舉沒有建構函式

1.3 解構函式

解構函式(destructor) 與建構函式相反,當物件脫離其作用域時(例如物件所在的函式已呼叫完畢),系統自動執行解構函式。解構函式往往用來做“清理善後” 的工作(例如在建立物件時用new開闢了一片記憶體空間,應在退出前在解構函式中用delete釋放)。

以C#語言為例,解構函式名也應與類名相同,只是在函式名前面加一個波浪符~

,例如~stud( ),以區別於建構函式。它不能帶任何引數,也沒有返回值(包括void型別)。只能有一個解構函式,不能過載。

語法:

~ 類名()
{
    //方法體
}    

2. 方法過載(overload)

同一個類中 方法名相同 引數列表(引數個數,引數型別)不同 稱為方法過載。

注意 方法過載與返回值型別無關

2.1 構造方法過載

舉例如下:

public SE()
{

}
public SE(int id)
{
    this.ID = id;
}
public SE(int id,String name) 
{
	this.ID = id;
    this.Name = name;
}

// 注意 多個過載的建構函式之間 可以使用 this關鍵字呼叫 
// 語法為:
public SE(int id,String name) : this(id)
{
    this.Name = name;
}

> 補充訪問修飾符:

C#中的訪問修飾符 以及許可權

public: 公共訪問,不受任何限制

private: 私有訪問,只限於本類成員訪問,子類和例項都訪問不到,類中成員沒寫修飾符,預設為private

protected: 受保護的,只能在本類或是子類中訪問,例項不能訪問

internal: 內部訪問,只限於在此專案中訪問,其他都訪問不到 如果類沒寫訪問修飾符,預設為internal

3. 擴充套件

3.1 軟體設計模式之單例模式:

單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。

通過單例模式可以保證系統中,應用該模式的類一個類只有一個例項。即一個類只有一個物件例項(例如 Windows系統中的回收站)

所以單例模式的要點有三個:

一是 :某個類只能有一個例項;

二是:它必須自行建立這個例項;

三是:它必須自行向整個系統提供這個例項。

設計核心:將構造器私有化,對外提供公有的獲取該類例項的方法

3.2 懶漢模式:

所謂懶漢模式,正如其名,比較懶,在類載入的時候並不建立自身例項,採用延遲載入的方式,只有在執行時呼叫了相關的方法才會被動建立自身的例項。

程式碼演示如下:

/// <summary>
/// 單例模式之懶漢模式
/// </summary>
public sealed class Singleton
{
    private static Singleton single;
    private Singleton() {}
    public static Singleton GetInstance()
    {
        if(null == single)
        {
            single = new Singleton();
        }
        return single;
    }
}

使用Main方法測試併發情況下,懶漢模式的執行緒安全問題,程式碼如下:

static void Main(string[] args)
{
    for (int i = 0; i < 10; i++)
    {
        new Thread(()=>
                   {
                       Console.WriteLine(Singleton.GetInstance().GetHashCode());
                   }).Start();
    }
    Console.ReadLine();
}

控制檯輸出如圖所示:
在這裡插入圖片描述

從輸出結果分析,很明顯 , 在多執行緒下無法正常工作,這也是致命的缺陷。

現在對上面的示例進行修改,因為最簡單的方法就是考慮同步,這裡採用synchronized實現。

/// <summary>
/// 單例模式之懶漢模式
/// </summary>
public sealed class Singleton
{
    private static Singleton single;
    private static readonly Object obj = new object();
    private Singleton() {}
    public static Singleton GetInstance()
    {
        if(null == single)
        {
            lock (obj)//解決執行緒併發時 系統建立多個例項的問題
            {
                if (null == single)
                    single = new Singleton();
            }
        }
        return single;
    }
}

以上寫法能夠在多執行緒併發環境中很好地工作,並且看起來它也具備了延遲載入的特性。但是很遺憾,這種處理方式效率不高,可以說95%以上的情況都不需要同步。

那麼對於執行緒安全問題,還有另一種解決方式,即餓漢模式。

3.3 餓漢模式:

餓漢模式在類載入的時候就已經完成了初始化操作,所以類載入較慢,但是獲取物件的速度很快。由於餓漢模式在類初始化時就完成了例項化,所以它是不存線上程安全問題的。修改以上的程式碼:

/// <summary>
/// 單例模式之餓漢模式
/// </summary>
public sealed class Singleton
{
    //餓漢式
    private static Singleton single = new Singleton();
    private Singleton() {  }
    public static Singleton GetInstance()
    {
    	return single;
    }
}    

上述程式碼中修改了GetInstance()方法,直接返回single,而此例項在類載入時就已經自行例項化了。這種方式基於classloader機制,有效避免了多執行緒的同步問題。

但是,由於導致類載入的原因比較多,而此時單例類ConfigManager在類載入時就例項化,顯然沒有達到延遲載入的效果。

現在可以對比一下兩種方式:

懶漢模式,在類載入時不建立例項,因此類載入速度快,但是執行時獲取物件的速度較慢,具備延遲載入的特性,但是又存線上程不安全的問題。

餓漢模式在類載入時就完成初始化,所以類載入較慢,但是獲取物件的速度很快。
懶漢模式是“時間換空間”,餓漢模式是“空間換時間”,因為一開始就建立了例項,所以每次使用時直接返回該例項就好了。

在實際開發場景中,例項化單例類很消耗資源,我們希望它可以延遲載入,顯然餓漢模式並不能實現。那麼我們應該怎麼處理呢?

要想讓餓漢模式同時具備延遲載入的特性,可以搭配靜態內部類進行改造實現。

改造程式碼如下:

/// <summary>
/// 單例模式之餓漢模式
/// </summary>
public sealed class Singleton
{
    //餓漢式
    private Singleton() {  }
    //使用靜態內部類 解決餓漢模式的延遲載入問題
    private static class Single
    {
        internal static readonly Singleton sing = new Singleton();
    }
    public static Singleton GetInstance()
    {
        retunr Single.sing;
    }
}   

總結:

對於單例模式的使用,不管是懶漢模式,餓漢模式,或者靜態內部類的方式,根據具體的業務需求而定。反正要遵守一個原則:

在整個程式執行期間,有且僅有一個例項。

若違背這一點,那麼即使設計的天花亂墜,也不是單例模式的實現。