1. 程式人生 > >Head First設計模式之原型模式

Head First設計模式之原型模式

webkit ble -1 否則 type sof 異常 構圖 etc

用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。

原型模式是一種比較簡單的模式,也非常容易理解,實現一個接口,重寫一個方法即完成了原型模式。在實際應用中,原型模式很少單獨出現。經常與其他模式混用,他的原型類Prototype也常用抽象類來替代。

二、結構圖

技術分享

原型模式主要用於對象的復制,它的核心是就是類圖中的原型類Prototype。Prototype類需要具備以下兩個條件:

  • 實現Cloneable接口。在java語言有一個Cloneable接口,它的作用只有一個,就是在運行時通知虛擬機可以安全地在實現了此接口的類上使用clone方法。在java虛擬機中,只有實現了這個接口的類才可以被拷貝,否則在運行時會拋出CloneNotSupportedException異常。
  • 重寫Object類中的clone方法。Java中,所有類的父類都是Object類,Object類中有一個clone方法,作用是返回對象的一個拷貝,但是其作用域protected類型的,一般的類無法調用,因此,Prototype類需要將clone方法的作用域修改為public類型。

三、實現

namespace DesignPatterns.Prototype
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> executors = new
List<string>(); executors.Add("張三"); executors.Add("李四"); Plan plan = new Plan(); plan.SetName("重構前端登錄界面"); plan.SetLevel(1); plan.SetStartdate(DateTime.Parse("2017-08-07")); plan.SetEnddate(DateTime.Parse(
"2017-08-09")); plan.SetExecutors(executors); Plan plan2 = plan.Clone(); plan2.SetName("後端接口改造"); plan2.SetLevel(2); plan2.SetStartdate(DateTime.Parse("2017-08-10")); plan2.SetEnddate(DateTime.Parse("2017-08-12")); Console.WriteLine("地址是否一樣?" + (plan == plan2)); Console.WriteLine("plan.getName() == plan2.getName() " + (plan.GetName() == plan2.GetName())); Console.WriteLine("plan.getLevel() == plan2.getLevel() " + (plan.GetLevel() == plan2.GetLevel())); Console.WriteLine("plan.getStartdate() == plan2.getStartdate() " + (plan.GetStartdate() == plan2.GetStartdate())); Console.WriteLine("plan.getEnddate() == plan2.getEnddate() " + (plan.GetEnddate() == plan2.GetEnddate())); Console.WriteLine("plan.getExecutors() == plan2.getExecutors() " + (plan.GetExecutors() == plan2.GetExecutors())); Console.WriteLine("plan:" + plan.toString()); Console.WriteLine("plan2:" + plan2.toString()); //plan任務比較重,在給plan添加一個人 executors.Add("王五"); plan.SetExecutors(executors); Console.WriteLine(); Console.WriteLine("地址是否一樣?" + (plan == plan2)); Console.WriteLine("plan.getName() == plan2.getName() " + (plan.GetName() == plan2.GetName())); Console.WriteLine("plan.getLevel() == plan2.getLevel() " + (plan.GetLevel() == plan2.GetLevel())); Console.WriteLine("plan.getStartdate() == plan2.getStartdate() " + (plan.GetStartdate() == plan2.GetStartdate())); Console.WriteLine("plan.getEnddate() == plan2.getEnddate() " + (plan.GetEnddate() == plan2.GetEnddate())); Console.WriteLine("plan.getExecutors() == plan2.getExecutors() " + (plan.GetExecutors() == plan2.GetExecutors())); Console.WriteLine("plan:" + plan.toString()); Console.WriteLine("plan2:" + plan2.toString()); } } /** * 計劃 * 【淺拷貝】 */ public class Plan { //計劃名稱 private string _name; //任務級別 private int _level; //開始時間 private DateTime _startdate; //截止時間 private DateTime _enddate; //執行人員 private List<string> _executors = new List<string>(); public Plan Clone() { return this; } public string GetName() { return _name; } public void SetName(string name) { this._name = name; } public DateTime GetStartdate() { return _startdate; } public void SetStartdate(DateTime startdate) { this._startdate = startdate; } public DateTime GetEnddate() { return _enddate; } public void SetEnddate(DateTime enddate) { this._enddate = enddate; } public List<string> GetExecutors() { return _executors; } public void SetExecutors(List<string> executors) { this._executors = executors; } public int GetLevel() { return _level; } public void SetLevel(int level) { this._level = level; } public string toString() { return "[name=" + _name + ", level=" + _level + ", startdate=" + _startdate + ", enddate=" + _enddate + ", executors=" + _executors + "]"; } } }

四、適用場景

1、資源優化場景。

2、類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。

3、性能和安全要求的場景。

4、通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。

5、一個對象多個修改者的場景。

6、一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。

7、在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個對象,然後由工廠方法提供給調用者。

註意事項:與通過對一個類進行實例化來構造新對象不同的是,原型模式是通過拷貝一個現有對象生成新對象的。淺拷貝實現 Cloneable,重寫,深拷貝是通過實現 Serializable 讀取二進制流。

五、優缺點

優點:

  1、對客戶端隱藏具體的實現類型:原型模式的客戶端,只知道原型接口的類型,並不知道具體的實現類型,從而減少了客戶端對這些具體實現類型的依賴。

  2、在運行時動態改變具體的實現類型:原型模式可以在運行期間,由客戶來註冊符合原型接口的實現類型,也可以動態的改變具體的實現類型,看起來接口沒有任何變化,但其實運行的已經是另外一個類實例了。因為克隆一個原型就類似於實例化一個類。

缺點:

  深度克隆方法實現會比較困難:原型模式最大的缺點就在於每個原型的子類都必須實現clone的操作,尤其在包含引用類型的對象時,clone方法會比較麻煩,必須要能夠遞歸的讓所有的相關對象都要正確的實現克隆。

參考:

http://www.cnblogs.com/JsonShare/p/7300124.html

http://www.runoob.com/design-pattern/prototype-pattern.html

歡迎閱讀本系列文章:Head First設計模式之目錄

Head First設計模式之原型模式