1. 程式人生 > 實用技巧 >Python+Appium自動化測試(16)-日誌採集(詳細)

Python+Appium自動化測試(16)-日誌採集(詳細)

這節講一下原型模式,原型模式用於解決大量相同或相似物件的建立問題,傳統的,我們例項化物件要用new關鍵字,在面對大量重複物件的建立情況下,new例項的過程是比較消耗資源的,所以我們可以利用一個物件作為原型,通過這個物件的不斷克隆自己來產出一個個新例項(這跟js的原型物件並不相同,讀者不要跟其做理論比較)。

我們可以設想一下,為何克隆比new例項要高效:拿畫畫來說,new例項相當於每次要構思這幅畫,並將其畫出來,克隆相當於第一次構思並畫出後,後續的畫都是臨摹,所以克隆是高效的。

我們看一下原型模式的定義:用一個已經建立的例項作為原型,通過複製該原型物件來建立一個和原型相同或相似的新物件。在這裡,原型例項指定了要建立的物件的種類。用這種方式建立物件非常高效,根本無須知道物件建立的細節。

在示例程式碼之前,先要理解一個概念:深拷貝和淺拷貝:

所謂淺拷貝就是指拷貝時只拷貝值型別的屬性,引用型別的屬性地址跟原型物件的地址指向一致,而深拷貝就是將原型物件的值型別和引用型別的屬性都拷貝一份,可以說是和原型物件完全分離開來。

接下來我們看一下如何讓一個物件可被克隆:

class prototypeClass : ICloneable
{
    public prototypeClass(string classname)
    {
        this.classname = classname;
    }
    public object Clone()
    {
        
return MemberwiseClone(); } ​ public string classname { get; set; } ​ public void ShowName() { Console.WriteLine(classname); } }

具體的邏輯就是讓原型類實現ICloneable介面,實現介面的Clone()方法,方法中呼叫MemberwiseClone()返回一個基於該原型物件淺拷貝的物件。

在主方法中呼叫,我們檢視一下執行結果:

prototypeClass p = new prototypeClass("
小明"); prototypeClass p_clone = (prototypeClass)p.Clone(); p.ShowName(); p_clone.ShowName(); Console.WriteLine(p == p_clone);

下面我再新增一個類,並在prototypeClass類中新增這個類作為屬性:

在主方法中比較一下克隆物件的s屬性是否與原型物件的s屬性相等:

執行結果如下:

結果為true,這就證明了此為淺拷貝。

若要實現深拷貝,需做點改動:

static prototypeClassS ps=new prototypeClassS("小艾");
public object Clone()
{
    prototypeClass p=(prototypeClass) MemberwiseClone();
    p.s=(prototypeClassS)ps.Clone();//手動呼叫屬性的克隆方法實現深度拷貝
    return p;
}

加入一個靜態原型屬性,每次克隆該原型物件時都去手動將引用物件克隆出來並賦值,如果被拷貝的屬性自己也有引用型別的屬性,為了實現深拷貝,也得做對應的修改,這樣就形成了一個拷貝鏈,層層深入,從而完成深度拷貝(其實這挺繁瑣的)。

下面我通過程式碼來演示一下new例項和克隆的效能差距:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
    prototypeClass clone = (prototypeClass)p.Clone();
}
​
stopwatch.Stop();
Console.WriteLine("克隆時間:" + stopwatch.Elapsed);
​
stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
    prototypeClass clone = new prototypeClass("小明",new prototypeClassS("新二"));
}
stopwatch.Stop();
Console.WriteLine("new 例項:" + stopwatch.Elapsed);

在主方法中編寫上述程式碼,下面看一下執行結果:

差距不言而喻。

當然,原型模式也有缺點:

  • 我們需要為每一個類都配置一個clone方法,clone方法位於類的內部,當對已有類進行改造的時候,需要修改程式碼,違背了開閉原則。

  • 當實現深克隆時,需要編寫較為複雜的程式碼,而且當物件之間存在多重巢狀引用時,為了實現深克隆,每一層物件對應的類都必須支援深克隆,實現起來會比較麻煩。

  個人公眾號,熱愛分享,知識無價。