• 工厂模式


    一、简单工厂

      简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。但由于经常被使用,所以给它一个“模式荣誉奖”。有些开发人员的确是把这个编程习惯误认为是“工厂模式”,不要因为简单工厂不是一个“真正的”模式,就忽略了它的用法。如下图显示的简单工厂使用类图(具体代码在文档最后列表中)。

      ★再提醒一次,在设计模式中,所谓的“实现以接口”并“不一定”表示“写一个类,并利用‘:’关键字来实现某个C#接口”。“实现一个接口”泛指“实现某个超类型(可以是类或接口)的某个方法”。

    二、工厂方法模式

      工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

    1.工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。如下类图,看看有哪些组成元素。

      我们可以看到,将一个OrderPizza()方法和一个工厂方法联合起来,就可以成为一个框架。除此之外,工厂方法将生产知识封装进各个创建者,这样的做法,也可以被视为是一个框架。

    如下图,看看这两个平行的类层级,并认清它们的关系:

    2.工厂方法模式能够封装具体类型的实例化。看看下面的类图,抽象的Creator提供了一个创建对象的方法的接口,也称为“工厂方法”。在抽象的Creator中,任何其他实现的方法,都可能使用到这个工厂方法所制造出来的产品,但只有子类真正实现这个工厂方法并创建产品。

    3.更多说明。

    问:当只有一个ConcreteCreator的时候,工厂方法模式有什么优点?

    答:尽管只有一个具体创建者,工厂方法模式依然很有用,因为它帮助我们将产品的“实现”从“使用”中解耦。如果增加产品或改变产品的实现,Creator并不会受到影响(因为Creator与任何ConcreteProduct之间都不是紧耦合)。

    问:对于简单工厂和工厂方法之间的差异,我依然感到困惑。它们看起来很类似,差别在于,在工厂方法中,返回比萨的类是子类。能解释一下吗?

    答:子类的确看起来像简单工厂。简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。比方说,在工厂方法中,OrderPizza()方法提供了一般的框架,以便创建比萨,OrderPizza()方法依赖工厂方法创建具体类,并制造出实际的比萨。可通过继承PizzaStore类,决定实际制造出的比萨是什么。简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

      根据上面的内容,我们可以推导出一个OO原则,即依赖倒置原则(Dependency Inversion Principle)

    4.依赖倒置原则:要依赖抽象,不要依赖具体类。

      首先,这个原则听起来很像是“针对接口编程,不针对实现编程”,不是吗?的确很相似,然而这里更强调“抽象”。这个原则说明了:不能让高层组件依赖底层组件,而且,不管高层或底层组件,“两者”都应该依赖于抽象。

      ★所谓“高层”组件,是由其它底层组件定义其行为的类。例如,PizzaStore是个高层组件,因为它的行为是由比萨定义的;PizzaStore创建所有不同的比萨对象,准备、烘烤、切片、装盒;而比萨本身属于底层组件。

    想要遵循依赖倒置原则,工厂方法并非是唯一的技巧,但却是最有威力的技巧之一。

    下面的指导方针,能帮你避免在OO设计中违反依赖倒置原则:

    (1)变量不可以持有具体类的引用。(如果使用new,就会持有具体类的引用。你可以改用工厂来避开这样的做法)

    (2)不要让类派生自具体类。(如果派生自具体类,你就会依赖具体类。请派生自一个抽象—接口、或抽象类)

    (3)不要覆盖基类中已实现的方法。(如果覆盖基类已经实现的方法,那么你的基类就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有的子类共享。)

    三、抽象工厂模式

      抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

    1.抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。如下类图来了解其中的关系。

    2.看看实际的关系类图,这是一张比较复杂的类图,我们可以从PizzaStore的观点来看看它。

    四、总结

    1. 所有的工厂都是用来封装对象的创建。
    2. 简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。
    3. 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。
    4. 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。
    5. 所有工厂模式都通过减少,应用程序和具体类之间的依赖促进松耦合。
    6. 工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。

    五、代码列表

    /// <summary>
    /// 比萨商店
    /// </summary>
    public abstract class PizzaStore
    {
        public Pizza OrderPizza(string type)
        {
            Pizza pizza = CreatePizza(type);
            pizza.Prepare();
            pizza.Bake();
            pizza.Cut();
            pizza.Box();
            return pizza;
        }
    
        protected abstract Pizza CreatePizza(string type);
    }
    /// <summary>
    /// 纽约比萨
    /// </summary>
    public class NYPizzaStore : PizzaStore
    {
        protected override Pizza CreatePizza(string type)
        {
            PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
            Pizza pizza = null;
            switch (type)
            {
                case "cheese":
                    pizza = new CheesePizza(ingredientFactory);
                    pizza.Name = "New York Style Cheese Pizza";
                    break;
                case "veggie":
                    pizza = new VeggiePizza(ingredientFactory);
                    pizza.Name = "New York Style Veggie Pizza";
                    break;
                case "clam":
                    pizza = new ClamPizza(ingredientFactory);
                    pizza.Name = "New York Style Clam Pizza";
                    break;
                case "pepperoni":
                    pizza = new PepperoniPizza(ingredientFactory);
                    pizza.Name = "New York Style Pepperoni Pizza";
                    break;
            }
            return pizza;
        }
    }
    /// <summary>
    /// 纽约披萨原料工厂
    /// </summary>
    public class NYPizzaIngredientFactory : PizzaIngredientFactory
    {
        public Dough CreateDough()
        {
            return new ThinCrustDough();
        }
    
        public Sauce CreateSauce()
        {
            return new MarinaraSauce();
        }
    
        public Cheese CreateCheese()
        {
            return new ReggianoCheese();
        }
    
        public Veggies[] CreateVeggies()
        {
            Veggies[] veggies = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
            return veggies;
        }
    
        public Pepperoni CreatePepperoni()
        {
            return new SlicedPepperoni();
        }
    
        public Clams CreateClam()
        {
            return new FreshClams();
        }
    }
    /// <summary>
    /// 芝加哥披萨原料工厂
    /// </summary>
    public class ChicagoPizzaIngredientFactory : PizzaIngredientFactory
    {
        public Dough CreateDough()
        {
            return new ThickCrustDough();
        }
    
        public Sauce CreateSauce()
        {
            return new PlumTomatoSauce();
        }
    
        public Cheese CreateCheese()
        {
            return new MozzarellaCheese();
        }
    
        public Veggies[] CreateVeggies()
        {
            Veggies[] veggies = { new BlackOlives(), new Spinach(), new EggPlant() };
            return veggies;
        }
    
        public Pepperoni CreatePepperoni()
        {
            return new SlicedPepperoni();
        }
    
        public Clams CreateClam()
        {
            return new FrozenClams();
        }
    }
    /// <summary>
    /// 芝加哥比萨商店
    /// </summary>
    public class ChicagoPizzaStore : PizzaStore
    {
        protected override Pizza CreatePizza(string type)
        {
            PizzaIngredientFactory ingredientFactory = new ChicagoPizzaIngredientFactory();
            Pizza pizza = null;
            switch (type)
            {
                case "cheese":
                    pizza = new CheesePizza(ingredientFactory);
                    pizza.Name = "Chicago Style Cheese Pizza";
                    break;
                case "veggie":
                    pizza = new VeggiePizza(ingredientFactory);
                    pizza.Name = "Chicago Style Veggie Pizza";
                    break;
                case "clam":
                    pizza = new ClamPizza(ingredientFactory);
                    pizza.Name = "Chicago Style Clam Pizza";
                    break;
                case "pepperoni":
                    pizza = new PepperoniPizza(ingredientFactory);
                    pizza.Name = "Chicago Style Pepperoni Pizza";
                    break;
            }
            return pizza;
        }
    }
    /// <summary>
    /// 披萨
    /// </summary>
    public abstract class Pizza
    {
        public string Name { get; set; }
        /// <summary>
        /// 材料:生面团
        /// </summary>
        public Dough MyDough { get; set; }
        /// <summary>
        /// 材料:酱油、调味汁
        /// </summary>
        public Sauce MySauce { get; set; }
        /// <summary>
        /// 材料:蔬菜
        /// </summary>
        public Veggies[] MyVeggies { get; set; }
        /// <summary>
        /// 材料:奶酪
        /// </summary>
        public Cheese MyCheese { get; set; }
        /// <summary>
        /// 材料:意大利辣香肠
        /// </summary>
        public Pepperoni MyPepperoni { get; set; }
        /// <summary>
        /// 材料:蛤蚌
        /// </summary>
        public Clams MyClams { get; set; }
        /// <summary>
        /// 预备
        /// </summary>
        public abstract void Prepare();
        /// <summary>
        /// 烘烤
        /// </summary>
        public void Bake()
        {
            Console.WriteLine("Bake for 25 minutes as 350");
        }
        /// <summary>
        /// 切片
        /// </summary>
        public void Cut()
        {
            Console.WriteLine("Cutting the pizza into diagonal slices");
        }
        /// <summary>
        /// 装箱
        /// </summary>
        public void Box()
        {
            Console.WriteLine("Place pizza in official PizzaStore box");
        }
    
        public override string ToString()
        {
            return "more pizza content";
        }
    }
    /// <summary>
    /// 奶酪披萨
    /// </summary>
    public class CheesePizza : Pizza
    {
        private PizzaIngredientFactory ingredientFactory;
    
        public CheesePizza(PizzaIngredientFactory _ingredientFactory)
        {
            ingredientFactory = _ingredientFactory;
        }
    
        public override void Prepare()
        {
            Console.WriteLine("Preparing {0}", Name);
            Console.WriteLine("     ingredient:Dough,Sauce,Cheese");
            MyDough = ingredientFactory.CreateDough();
            MySauce = ingredientFactory.CreateSauce();
            MyCheese = ingredientFactory.CreateCheese();
        }
    }
    /// <summary>
    /// 蛤蚌比萨
    /// </summary>
    public class ClamPizza : Pizza
    {
        private PizzaIngredientFactory ingredientFactory;
    
        public ClamPizza(PizzaIngredientFactory _ingredientFactory)
        {
            ingredientFactory = _ingredientFactory;
        }
        public override void Prepare()
        {
            Console.WriteLine("Preparing {0}", Name);
            Console.WriteLine("     ingredient:Dough,Sauce,Cheese,Clam");
            MyDough = ingredientFactory.CreateDough();
            MySauce = ingredientFactory.CreateSauce();
            MyCheese = ingredientFactory.CreateCheese();
            MyClams = ingredientFactory.CreateClam();
        }
    }
    /// <summary>
    /// 辣香肠比萨
    /// </summary>
    public class PepperoniPizza : Pizza
    {
        private PizzaIngredientFactory ingredientFactory;
    
        public PepperoniPizza(PizzaIngredientFactory _ingredientFactory)
        {
            ingredientFactory = _ingredientFactory;
        }
        public override void Prepare()
        {
            Console.WriteLine("Preparing {0}", Name);
            Console.WriteLine("     ingredient:Dough,Sauce,Pepperoni");
            MyDough = ingredientFactory.CreateDough();
            MySauce = ingredientFactory.CreateSauce();
            MyPepperoni = ingredientFactory.CreatePepperoni();
        }
    }
    /// <summary>
    /// 蔬菜比萨
    /// </summary>
    public class VeggiePizza : Pizza
    {
        private PizzaIngredientFactory ingredientFactory;
    
        public VeggiePizza(PizzaIngredientFactory _ingredientFactory)
        {
            ingredientFactory = _ingredientFactory;
        }
        public override void Prepare()
        {
            Console.WriteLine("Preparing {0}", Name);
            Console.WriteLine("     ingredient:Dough,Sauce,Veggies");
            MyDough = ingredientFactory.CreateDough();
            MySauce = ingredientFactory.CreateSauce();
            MyVeggies = ingredientFactory.CreateVeggies();
        }
    }
    /// <summary>
    /// 简单比萨工厂
    /// </summary>
    public class SimplePizzaFacotry
    {
        public Pizza CreatePizza(string type)
        {
            Pizza pizza = null;
            switch (type)
            {
                case "cheese":
                    pizza = new CheesePizza(null);
                    break;
                case "pepperoni":
                    pizza = new PepperoniPizza(null);
                    break;
                case "veggie":
                    pizza = new VeggiePizza(null);
                    break;
                case "clam":
                    pizza = new ClamPizza(null);
                    break;
            }
            return pizza;
        }
    }
    /// <summary>
     /// 奶酪
     /// </summary>
     public abstract class Cheese
     {
          
     }
     /// <summary>
     /// 巴马干酪
     /// </summary>
     public class ReggianoCheese : Cheese
     {
         
     }
     /// <summary>
     /// 马苏里拉奶酪
     /// </summary>
     public class MozzarellaCheese : Cheese
     {
    
     }
     /// <summary>
     /// 山羊乳干酪
     /// </summary>
     public class GoatCheese : Cheese
     {
    
     }
    /// <summary>
    /// 蛤蚌
    /// </summary>
    public abstract class Clams
    {
         
    }
    /// <summary>
    /// 新鲜蛤蚌
    /// </summary>
    public class FreshClams : Clams
    {
        
    }
    /// <summary>
    /// 冰冻蛤蚌
    /// </summary>
    public class FrozenClams : Clams
    {
    
    }
    /// <summary>
    /// 鱿鱼蛤蚌
    /// </summary>
    public class CalamariClams : Clams
    {
    
    }
    /// <summary>
    /// 生面团
    /// </summary>
    public abstract class Dough
    {
    
    }
    /// <summary>
    /// 稀薄面团
    /// </summary>
    public class ThinCrustDough : Dough
    {
        
    }
    /// <summary>
    /// 加厚面团
    /// </summary>
    public class ThickCrustDough : Dough
    {
    
    }
    /// <summary>
    /// 很薄面团
    /// </summary>
    public class VeryThinCrustDough : Dough
    {
    
    }
    /// <summary>
    /// 意大利辣香肠
    /// </summary>
    public abstract class Pepperoni
    {
         
    }
    /// <summary>
    /// 切片意大利辣香肠
    /// </summary>
    public class SlicedPepperoni : Pepperoni
    {
        
    }
    /// <summary>
    /// 酱油、调味汁
    /// </summary>
    public abstract class Sauce
    {
    
    }
    /// <summary>
    /// 海员式沙司
    /// </summary>
    public class MarinaraSauce : Sauce
    {
    
    }
    /// <summary>
    /// 梨形番茄
    /// </summary>
    public class PlumTomatoSauce : Sauce
    {
    
    }
    /// <summary>
    /// 蒜末沙拉
    /// </summary>
    public class BruschettaSauce : Sauce
    {
    
    }
    /// <summary>
    /// 蔬菜
    /// </summary>
    public abstract class Veggies
    {
    
    }
    /// <summary>
    /// 大蒜
    /// </summary>
    public class Garlic : Veggies
    {
    
    }
    /// <summary>
    /// 洋葱
    /// </summary>
    public class Onion : Veggies
    {
    
    }
    /// <summary>
    /// 蘑菇
    /// </summary>
    public class Mushroom : Veggies
    {
    
    }
    /// <summary>
    /// 红辣椒
    /// </summary>
    public class RedPepper : Veggies
    {
        
    }
    /// <summary>
    /// 菠菜
    /// </summary>
    public class Spinach : Veggies
    {
    
    }
    /// <summary>
    /// 乌榄
    /// </summary>
    public class BlackOlives : Veggies
    {
    
    }
    /// <summary>
    /// 茄子
    /// </summary>
    public class EggPlant : Veggies
    {
    
    }
    View Code

    -----------------------------以上内容根据《Head First 设计模式》进行整理

  • 相关阅读:
    js 音乐播放器
    音频播放器在chrome浏览器,play报错
    CSS多行文字超出隐藏加省略号
    css 清楚浮动的几种方式
    npm -g -D -s的区别
    electron-vue初始桌面应用
    vue 关闭浏览器
    webpack基础
    京东数科-百度BCOT---面试
    HTTP面试题
  • 原文地址:https://www.cnblogs.com/zwt-blog/p/6594484.html
Copyright © 2020-2023  润新知