程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 七、創建型模式之建造者、原型、單例-----《大話設計模式》,大話西游2人物原型

七、創建型模式之建造者、原型、單例-----《大話設計模式》,大話西游2人物原型

編輯:C#入門知識

七、創建型模式之建造者、原型、單例-----《大話設計模式》,大話西游2人物原型


一、建造者模式

    將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。

    建造者模式的好處就是使得建造代碼與表示代碼分離,由於建造者隱藏了該產品是如何組裝的,所以若需要改變一個產品的內部表示,只需要再定義一個具體的建造者就可以了。

    指揮者這個類用來控制建造過程,也用來隔離用戶與建造過程的關聯。

   Builder:人

   ConcreteBuilder1:胖子

   ConcreteBuilder2:瘦子

   Director:開始組裝

   Product:成果

  

//具體產品類,最終形成的產品樣式 class Product { //產品的組成部分的集合 IList<string> parts = new List<string>(); //增加部件 public void Add(string part) { parts.Add(part); } //列舉所有的產品部件 public void Show() { Console.WriteLine("\n產品 創建 ----"); foreach (string part in parts) { Console.WriteLine(part); } } }

//抽象建造者類,確定有幾個部件,並返回產品
abstract class Builder
    {
        //兩個部件組成
        public abstract void BuildPartA();
        public abstract void BuildPartB();
        public abstract Product GetResult();
    }

   //產品A實現類
    class ConcreteBuilder1 : Builder
    {
        private Product product = new Product();
        
        //將部件A組裝到產品上
        public override void BuildPartA()
        {
            product.Add("部件A");
        }

        //將部件B組裝到產品上
        public override void BuildPartB()
        {
            product.Add("部件B");
        }

        public override Product GetResult()
        {
            return product;
        }
    }

    //產品B實現類
    class ConcreteBuilder2 : Builder
    {
        private Product product = new Product();
        public override void BuildPartA()
        {
            product.Add("部件X");
        }

        public override void BuildPartB()
        {
            product.Add("部件Y");
        }

        public override Product GetResult()
        {
            return product;
        }
    }
//指揮者類
 class Director
    {
        public void Construct(Builder builder)
        {
           //創建部件A
            builder.BuildPartA();

            //創建部件B
            builder.BuildPartB();
        }
    }
//客戶端代碼
static void Main(string[] args)
        {
            //初始化一個指揮者
            Director director = new Director();
            //初始化兩個具體產品類
            Builder b1 = new ConcreteBuilder1();
          Builder b2 = new ConcreteBuilder2();

            //創建產品A
          director.Construct(b1);
            //獲得最終產品
            Product p1 = b1.GetResult();
           p1.Show();

            //創建產品B
          director.Construct(b2);
           //獲得最終產品
            Product p2 = b2.GetResult();
           p2.Show();

           Console.Read();
        }

二、原型模式

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

    原型模式其實就是從一個對象再創建另外一個可定制的對象,而且不需要知道任何創建的細節。

    一般在初始化的信息不發生變化的情況下,克隆是最好的辦法,這樣既隱藏了對象創建的細節,又對性能是大大的提高,不用重新初始化對象,而是動態地獲得對象運行時的狀態。

//抽象原型類 abstract class Prototype { private string id; // 構造函數

        public Prototype(string id)
        {
            this.id = id;
        }

        // 屬性 
        public string Id
        {
            get { return id; }
        }
       
        public abstract Prototype Clone();
    }

    //具體原型類1
    class ConcretePrototype1 : Prototype
    {
        public ConcretePrototype1(string id): base(id)
        {
        }

       //創建當前對象的淺表副本
        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();
        }
    }

    //也可以通過實現NET提供的ICloneable接口來取代抽象類
    class ConcretePrototype2 : ICloneable
    {        
       private string id;

        // 構造函數
        public ConcretePrototype2 (string id)
        {
            this.id = id;
        }
        public string Id 
       { 
get { return id; } 
       }

        public Object Clone()
        {
            return (Object)this.MemberwiseClone();
        }
    }
//客戶端代碼 
static void Main(string[] args)
        {
            //創建p1
            ConcretePrototype1 p1 = new ConcretePrototype1("I");
           //復制給c1
            ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
            Console.WriteLine("Cloned: {0}", c1.Id);

            ConcretePrototype2 p2 = new ConcretePrototype2("II");
            ConcretePrototype2 c2 = (ConcretePrototype2)p2.Clone();
            Console.WriteLine("Cloned: {0}", c2.Id);

            // Wait for user 
            Console.Read();

        }

淺表復制(MemberwiseClone()):如果字段是值類型的,則對該字段執行逐位復制;如果字段是引用類型,則復制引用但不復制引用的對象;因此,原始對象及其復本引用同一對象。

深復制:把引用對象的變量指向復制過的新對象,而不是原有的被引用的對象。如果需要深復制,需要在復制方法中編寫程序,把任何形式類型轉換成值類型再復制一次。

三、單例模式

    保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

    所有類都有構造方法,不編碼則系統默認生成空的構造方法,若有顯式定義的構造方法,默認的構造方法就會失效,將構造方法的修飾符改為private,則外部程序就不能用new來實例化它了。

    優勢:讓類自身復制保持它的唯一實例。這個類可以保證沒有其他實例可以被創建,並且還提供了一個訪問該實例的方法(對唯一的實例可以嚴格地控制用戶怎樣及何時訪問它)。

//Singleton類 class Singleton { private static Singleton instance; private static readonly object syncRoot = new object(); //修改構造方法修飾符,使外界不能利用new創建實例 private Singleton() { } //創建實例 public static Singleton GetInstance() { //雙重鎖定,先判斷實例是否存在,不存在再加鎖處理 if (instance == null) { //不存在,則加線程鎖,防止其他線程在前一個線程沒有執行完的時候再次創建 lock (syncRoot) { if (instance == null) { //初始化實例 instance = new Singleton(); } } } return instance; } }

//客戶端代碼 
static void Main(string[] args)
        {
            //用此方法初始化實例   
            Singleton s1 = Singleton.GetInstance();
            //由於s1已經創建了實例,則s2不會再次創建新實例
            Singleton s2 = Singleton.GetInstance();

            if (s1 == s2)
            {
                Console.WriteLine("Objects are the same instance");
            }

            Console.Read();
        }

PS:lock是確保當一個線程位於代碼的臨界區時,另一個線程不進入臨界區。如果其他線程試圖進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。

四、衍生

    靜態初始化:c#與公共語言運行庫提供了一種“靜態初始化”方法,這種方法不需要開發人員顯式地編寫線程安全代碼,即可解決多線程環境下它是不安全的問題。

    餓漢式單例類:靜態初始化的方式是在自己被加載時就將自己實例化。一般已經足夠使用

    懶漢式單例類:在第一次被引用時,才會將自己實例化。

//增加sealed修飾符,阻止發生派生,而派生可能會增加實例
public sealed class Singleton
    {
       //在第一次引用類的任何成員時創建實例
        private static readonly Singleton instance = new Singleton();

        private Singleton() { }

        public static Singleton GetInstance()
        {
            return instance;
        }
    }

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