程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 設計模式,設計模式java

設計模式,設計模式java

編輯:C#入門知識

設計模式,設計模式java


原型模式從字面上來看, 可能還不是那麼通俗, 通俗點講, 可以說是拷貝模式.

 從拷貝來說, 有完全拷貝, 和不完全拷貝. 就仿佛孫猴子的吹毛生猴, 但是這些小猴子明顯就沒有孫悟空本體厲害, 這種拷貝, 算是淺拷貝吧. 

既然有淺拷貝, 那肯定也是有深拷貝的. 深拷貝就是小猴子與孫悟空本體一樣厲害, 無論是從本事還是從長相, 都是一樣的

一、原型

/// <summary>
/// 原型
/// </summary>
abstract public class Prototype
{
public int Id { get; set; }

public string Name { get; set; }

public List<int> Size = new List<int>();

public Prototype(int id)
{
    this.Id = id;
}

abstract public Prototype Clone();
}

原型上, 我放了一個值類型, 一個字符串, 一個整形集合, 在原型模式下, 我會修改這幾個值, 來觀察克隆之後的變化

 

二、淺拷貝

public class Concrete1 : Prototype
{
    public Concrete1(int id)
        : base(id)
    { }

    public override Prototype Clone()
    {
        return (Prototype)this.MemberwiseClone();
    }
}

測試代碼:

Console.WriteLine("--------------淺拷貝----------------------");
Concrete1 p1 = new Concrete1(1);
p1.Name = "Name";
p1.Size.AddRange(new int[] { 1, 2, 3, 4, 5 });
Concrete1 c1 = (Concrete1)p1.Clone();
Console.WriteLine("Before Concrete1 change");
Console.WriteLine("Cloned : Id - {0}, Name - {1}, Size - {2}", c1.Id, c1.Name, string.Join(",", c1.Size));

Console.WriteLine();
p1.Id = 2;
p1.Name = "p1.Name";
p1.Size.AddRange(new int[] { 6, 7, 8, 9 });

Console.WriteLine("After Concrete1 changed");
Console.WriteLine("Cloned : Id - {0}, Name - {1}, Size - {2}", c1.Id, c1.Name, string.Join(",", c1.Size));

結果:

可以看到, 我在克隆之後, 修改了原型集合的值,  克隆對象也跟著改變了, 說明他們的集合變量指向同一塊堆空間. 

Console.WriteLine("p1.Size == c1.Size, {0}", p1.Size == c1.Size);

有圖有真相.

 

三、深拷貝

public class Concrete2 : Prototype
{
    public Concrete2(int id)
        : base(id)
    { }

    public override Prototype Clone()
    {var jsonStr = JsonConvert.SerializeObject(this);return JsonConvert.DeserializeObject<Concrete2>(jsonStr);
    }
}

測試代碼:

Console.WriteLine("--------------深拷貝----------------------");
Concrete2 p2 = new Concrete2(2);
p2.Name = "Name";
p2.Size.AddRange(new int[] { 1, 2, 3, 4, 5 });
Concrete2 c2 = (Concrete2)p2.Clone();
Console.WriteLine("Before Concrete2 change");
Console.WriteLine("Cloned : Id - {0}, Name - {2}, Size - {2}", c2.Id, c2.Name, string.Join(",", c2.Size));

Console.WriteLine();
p2.Id = 2;
p2.Name = "p2.Name";
p2.Size.AddRange(new int[] { 6, 7, 8, 9 });

Console.WriteLine("After Concrete2 changed");
Console.WriteLine("Cloned : Id - {0}, Name - {2}, Size - {2}", c2.Id, c2.Name, string.Join(",", c2.Size));

Console.WriteLine("p2.Size == c2.Size, {0}", p2.Size == c2.Size);

 結果:

可以看到, 拷貝實體並沒有任何變化, 說明他們已經是兩個獨立的分開的實體. 並沒有共同的變量引用(方法引用除外).

在這裡, 我實現深拷貝的方式是通過序列化的方式, 當然還有很多別的方式. 可以自己實現. C#提供的那個克隆方法, 是淺拷貝的實現.

C#有一個接口:ICloneable, 如果不想做成抽象類, 也可以通過這個接口去實現.

 

四、個人應用

就我個人在項目中的應用來看, 最近使用過結構克隆.

Datatble這個變量, 無論是b/s, 還是c/s, 應該都是用過的吧.

它有一個Clone方法, 可以用來克隆表結構和約束, 相當方便, 我不需要再去做一遍繁雜的表結構創建.

 

參考:

大話設計模式

C#設計模式(9)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved