(待完善)五種創建型設計模式總結

  • 創建型模式

這些設計模式提供了一種在創建對象的同時隱藏創建邏輯的方式,而不是使用 new 運算符直接實例化對象。這使得程序在判斷針對某個給定實例需要創建哪些對象時更加靈活。

  • 分類
  1. 工廠模式(Factory Pattern)
  2. 抽象工廠模式(Abstract Factory Pattern)
  3. 單例模式(Singleton Pattern)
  4. 建造者模式(Builder Pattern)
  5. 原型模式(Prototype Pattern)
  • 工廠模式(Factory Pattern)

定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。


C#: public abstract class Product    //抽象產品類
    {
        public abstract void method();    //抽象方法
    }
    public class ConcreteProduct:Product    //具體產品類
    {
        public override void method()
        {
            //業務邏輯處理
        }
    }
    public class Factory    //工廠類
    {
        //根據類名創建對象
        public Product GetProduct(String name)
        {
            if (name.Equals("ConcreteProduct", StringComparison.CurrentCultureIgnoreCase)) return new ConcreteProduct();
            return null;
        }
        //根據類型創建對象
        public static Product getProduct(Type type)
        {
            //判斷type是否繼承了Shape接口
            if (typeof(Product).IsAssignableFrom(type))
                return (Product)Activator.CreateInstance(type);
            return null;
        }
    }
    public class Client    //場景類
    {
        public static void Main(string[] args)
        {
            Factory factory = new Factory();
            Product p1 = factory.GetProduct("concreteproduct");
            Product p2 = Factory.getProduct(typeof(ConcreteProduct));
        }
    }

優點: 1、一個調用者想創建一個對象,只要知道其名稱就可以了。 

            2、擴展性高,如果想增加一個產品,只要擴展一個工廠類就可以。 

            3、屏蔽產品的具體實現,調用者只關心產品的接口。

缺點:每次增加一個產品時,都需要增加一個具體類和對象實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。

注意事項作爲一種創建類模式,在任何需要生成複雜對象的地方,都可以使用工廠方法模式。有一點需要注意的地方就是複雜對象適合使用工廠模式,而簡單對象,特別是只需要通過 new 就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的複雜度。

  • 抽象工廠模式(Abstract Factory Pattern)

提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。


    public interface IProduct
    {
        public void method1();
    }
    public abstract class AbstractProduct1:IProduct
    {
        public abstract void method2();
    }
    public abstract class AbstractProduct2 : IProduct
    {
        public abstract void method2();
    }
    public class ConcreteProduct1 : AbstractProduct1
    {
        public override void method2()
        {
            //業務邏輯處理
        }
        public  void method1()
        {
            //業務邏輯處理
        }
    }
    public class ConcreteProduct2 : AbstractProduct2
    {
        public override void method2()
        {
            //業務邏輯處理
        }
        public void method1()
        {
            //業務邏輯處理
        }
    }
    public abstract class AbstractFactory
    {
        //有幾個產品簇的工廠就有幾個實現方法
        public abstract AbstractProduct1 GetProduct1(string name);
        public abstract AbstractProduct2 GetProduct2(string name);
    }
    public class Factory1:AbstractFactory
    {
        //根據類名創建對象
        public override AbstractProduct1 GetProduct1(String name)
        {
            if (name.Equals("ConcreteProduct1", StringComparison.CurrentCultureIgnoreCase)) return new ConcreteProduct1();
            return null;
        }
    }
    public class Factory2 : AbstractFactory
    {
        //根據類名創建對象
        public override AbstractProduct2 GetProduct2(String name)
        {
            if (name.Equals("ConcreteProduct2", StringComparison.CurrentCultureIgnoreCase)) return new ConcreteProduct2();
            return null;
        }
    }
    public class FactoryCreator    //創建工廠的類
    {
        //根據類名創建對象
        public static AbstractFactory GetFactory(String name)
        {
            if (name.Equals("Factory1", StringComparison.CurrentCultureIgnoreCase)) return new Factory1();
            if (name.Equals("Factory2", StringComparison.CurrentCultureIgnoreCase)) return new Factory2();
            return null;
        }
    }
    public class Client
    {
        public static void Main(string[] args)
        {
            //AbstractFactory factory1 = new Factory1();
            //AbstractFactory factory2 = new Factory2();
            AbstractFactory factory1 = FactoryCreator.GetFactory("Factory1");
            AbstractFactory factory2 = FactoryCreator.GetFactory("Factory2");
            ConcreteProduct1 p1 = factory1.GetProduct1("concreteproduct1") as ConcreteProduct1;
            ConcreteProduct2 p2 = factory2.GetProduct2("concreteproduct2") as ConcreteProduct2;
        }
    }

優點:當一個產品族中的多個對象被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的對象。

缺點:產品族擴展非常困難,要增加一個系列的某一產品,既要在抽象的 Creator 里加代碼,又要在具體的裏面加代碼。

注意事項:產品族難擴展(改動太大,不符合開閉原則),產品等級易擴展。

  • 單例模式(Singleton Pattern)

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


c#  public class Singleton
    {
        private static Singleton instance = new Singleton();
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
        public void ShowMessage()
        {
            Console.WriteLine("this is a singleObject");
        }
    }
    public class Client
    {
        static void Main(string[] args)
        {
            Singleton.Instance.ShowMessage();
        }
    }

優點: 1、在內存裏只有一個實例,減少了內存的開銷,尤其是頻繁的創建和銷燬實例(比如管理學院首頁頁面緩存)。 

            2、避免對資源的多重佔用(比如寫文件操作)。

缺點:沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。

注意事項:getInstance() 方法中需要使用同步鎖 synchronized (Singleton.class) 防止多線程同時進入造成 instance 被多次實例化。當前是線程不安全的。


  • 建造者模式(Builder Pattern)
將一個複雜的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。

建造者模式(Builder Pattern)使用多個簡單的對象一步一步構建成一個複雜的對象。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

一個 Builder 類會一步一步構造最終的對象。該 Builder 類是獨立於其他對象的。

    public class Product
    {
        public void doSomething()
        {
            //獨立業務處理
        }
    }
    public abstract class Builder
    {
        public abstract void setPart();//設置產品的不同部分,以獲得新的產品
        public abstract Product buildProduct();//建造產品
    }
    public class ConcreteBuilder:Builder
    {
        private Product product = new Product();
        //設置產品零件
        public override void setPart()
        {
            //產品類內的邏輯處理
        }
        //組建一個產品
        public override Product buildProduct()
        {
            return product;
        }
    }
    public class Director
    {
        private Builder builder = new ConcreteBuilder();
        //構建不同的產品
        public Product getAProduct()
        {
            builder.setPart();
            //設置不同的零件,產生不同的產品
            return builder.buildProduct();
        }
    }
    public class Client
    {
        static void Main(string[] args)
        {
            Director director = new Director();
            Product product = director.getAProduct();
        }
    }

優點: 1、建造者獨立,易擴展。 

            2、便於控制細節風險。

缺點: 1、產品必須有共同點,範圍有限制。

            2、如內部變化複雜,會有很多的建造類。

使用場景: 1、需要生成的對象具有複雜的內部結構。 2、需要生成的對象內部屬性本身相互依賴。

注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。與模版方法模式結合使用更佳(產品類中使用模版方法)


  • 原型模式(Prototype Pattern)

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

原型模式(Prototype Pattern)是用於創建重複的對象,同時又能保證性能。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

這種模式是實現了一個原型接口,該接口用於創建當前對象的克隆。當直接創建對象的代價比較大時,則採用這種模式。例如,一個對象需要在一個高代價的數據庫操作之後被創建。我們可以緩存該對象,在下一個請求時返回它的克隆,在需要的時候更新數據庫,以此來減少數據庫調用。


    public class Client
    {
        static void Main(string[] args)
        {
            Prototype pt1 = new Prototype();
            Prototype pt2 = (Prototype)pt1.Clone();
            Console.WriteLine(pt2.name);
        }
    }
    public class Prototype : ICloneable    //實現接口
    {
        public string name = "ssss";
        public object Clone()
        {
            object obj = null;
            try
            {
                obj = this.MemberwiseClone();//淺拷貝
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                //異常處理
            }
            return obj;
        }
    }

優點: 1、性能提高。 2、逃避構造函數的約束。

缺點: 1、配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。 2、必須實現 ICloneable 接口。

使用場景: 1、資源優化場景。 2、類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。 3、性能和安全要求的場景。 4、通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。 5、一個對象多個修改者的場景。 6、一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。 7、在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個對象,然後由工廠方法提供給調用者。

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



發佈了44 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章