工厂模式

一、简单工厂

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

  ★再提醒一次,在设计模式中,所谓的“实现以接口”并“不一定”表示“写一个类,并利用‘:’关键字来实现某个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 设计模式》进行整理

原文地址:https://www.cnblogs.com/zwt-blog/p/6594484.html