山西面馆中的设计模式——建造者模式

引言

将学习融入生活中,是件很happy的事情,不会感觉到累。一个感觉:很好玩!挺开心的......

为什么会出现建造者模式?

在软件系统中,有时面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成。

这个复杂的对象的各个部分经常面临剧烈变化,但是将它们组合在一起的算法却相对稳定。

比如:建一所房子,建房子的过程基本不变(算法:画图-地基-建造),但是门窗之类的组建确是易变的。

怎么应对这种变化?

如何提供一种“封装机制“来隔离出”复杂对象的各个部分“的变化,从而保持系统中的”稳定构建算法“不随需求改变而改变,这就是建造者模式。

使用建造者模式的目的?

将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

建造者模式定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

一步步创建复杂的对象,它允许用户只通过制定复杂对象的类型和内容就可以创建它们,用户不知道内部的具体构建细节。

建造者模式类图

建造者模式参与者

抽象建造者(Builder)

为创建一个产品角色对象的各个部件指定抽象接口。

具体建造者(Conctrete Builder)

实现抽象建造者接口,构造和装配产品的各个部件。

定义并明确它所创建的表示。

提供一个返回这个产品的接口。

指挥者(Director)

构建一个使用抽象建造者接口的对象。

产品角色(Product)

被构建的复杂对象,具体建造者创建该产品的内部表示并定义它的装配过程。

包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

实例分析

场景:lz现在在前台点一份大份量的鸡蛋面,据吃货所知,山西面馆中,对鸡蛋面提供三种的做法,1.普通分量的 2.加2元面的大份量的 3.加一个鸡蛋的营养餐。

分析:

抽象建造者:家传制面秘方(算法),所有鸡蛋面的制作过程均要遵循本秘方,否则是砸自己的招牌啊。

具体的建造者:小康师傅(水平有限,面的多少把握不够,徒弟级别),康师傅(多年砍面技术溶于一身,造就了神般的人物,要砍多少面就多少,不多不少正好),康氏(女人,总比男人更懂得营养,营养师级别人物)

指挥者:收银员,根据order指挥这份面如何来做(是否加量,是否加鸡蛋)。

产品角色:鸡蛋面。

代码实现:

建造者 指定不变的创建过程(算法)


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace Wolfy.建造者模式
 {
     /// <summary>
     /// 为创建产品指定相对稳定的算法(步骤)
     /// </summary>
     public abstract class Builder
     {
         /// <summary>
         /// 水温
         /// </summary>
         public abstract void WaterTemperature();
         /// <summary>
         /// 削多少下面
         /// </summary>
         public abstract void CutTimesWheatflour();
         /// <summary>
         /// 添加西红柿
         /// </summary>
         public abstract void AddTomattos();
         /// <summary>
         /// 添加鸡蛋
         /// </summary>
         public abstract void AddEggs();
         /// <summary>
         /// 搅拌
         /// </summary>
         public abstract void Stir();
         /// <summary>
         /// 返回
         /// </summary>
         public abstract Food BuildFood();
     }
 }

具体建造者


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace Wolfy.建造者模式
 {
     /// <summary>
     /// 建造者模式中的具体建造者 小康师傅类 负责普通鸡蛋面的生产
     /// </summary>
     public class LittleMasterKang : Builder
     {
         Food normalFood = new Food();
         public override void WaterTemperature()
         {
             Console.WriteLine("小康师傅:嗯,水温有100℃了,可以下面了");
             normalFood.DicFood.Add("汤",);
         }
 
         public override void CutTimesWheatflour()
         {
             Console.WriteLine("小康师傅:咔咔.....嗯,够了");
             normalFood.DicFood.Add("面",5f);
         }
 
         public override void AddTomattos()
         {
             Console.WriteLine("小康师傅:切两个西红柿,咔咔.....放入锅中");
             normalFood.DicFood.Add("西红柿",2f);
         }
 
         public override void AddEggs()
         {
             Console.WriteLine("小康师傅:鸡蛋");
             normalFood.DicFood.Add("鸡蛋",3f);
         }
 
         public override void Stir()
         {
             Console.WriteLine("小康师傅:一圈,二圈,三圈....{0}圈,嗯,够了", ); 
         }
         /// <summary>
         /// 返回食物
         /// </summary>
         public override Food BuildFood()
         {
             return normalFood;
         }
     }
 }


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace Wolfy.建造者模式
 {
     /// <summary>
     /// 具体建造者 大师级的康师傅类 用来生产大份量的套餐 
     /// </summary>
     public class MasterKang : Builder
     {
         Food normalFood = new Food();
         public override void WaterTemperature()
         {
             Console.WriteLine("小康师傅:嗯,水温有100℃了,可以下面了");
             normalFood.DicFood.Add("汤", );
         }
 
         public override void CutTimesWheatflour()
         {
             Console.WriteLine("康师傅:咔咔.....嗯,够了");
             normalFood.DicFood.Add("面(2¥)", 7f);
         }
 
         public override void AddTomattos()
         {
             Console.WriteLine("康师傅:切两个西红柿,咔咔.....放入锅中");
             normalFood.DicFood.Add("西红柿", 2f);
         }
 
         public override void AddEggs()
         {
             Console.WriteLine("康师傅:鸡蛋");
             normalFood.DicFood.Add("鸡蛋", 3f);
         }
 
         public override void Stir()
         {
             Console.WriteLine("康师傅:一圈,二圈,三圈....{0}圈,嗯,够了", 60);
         }
         /// <summary>
         /// 返回食物
         /// </summary>
         public override Food BuildFood()
         {
             return normalFood;
         }
     }
 }

指挥者


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace Wolfy.建造者模式
 {
     /// <summary>
     /// 收银员类 即建造者模式中的指挥者 根据订单指挥 到底做什么样的面
     /// </summary>
     public class Cashier
     {
         public void BuidFood(Builder builder)
         {
             builder.WaterTemperature();
             builder.CutTimesWheatflour();
             builder.AddTomattos();
             builder.AddEggs();
             builder.Stir();
         }
     }
 }

产品Food


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace Wolfy.建造者模式
 {
     /// <summary>
     /// 产品类
     /// </summary>
     public class Food
     {
         Dictionary<string, double> dicFood;
 
         public Dictionary<string, double> DicFood
         {
             get { return dicFood; }
             set { dicFood = value; }
         }
         public Food()
         {
             dicFood = new Dictionary<string, double>();
         }
         private double price;
         private string foodName;
         public void ShowFood()
         {
             foreach (KeyValuePair<string, double> item in dicFood)
             {
                 foodName += item.Key + ",";
                 price += item.Value;
             }
             string[] food = foodName.TrimEnd(',').Split(',');
             //为了显示 按正常的顺序显示
             foodName = food[] + food[] + food[] + food[];
             Console.WriteLine(foodName + "\t" + price + "¥");
         }
     }
 }

控制台代码

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace Wolfy.建造者模式
 {
     class Program
     {
         static void Main(string[] args)
         {
             //创建指挥者 
             Cashier director = new Cashier();
             //创建普通鸡蛋面的制造者 小康师傅
             LittleMasterKang kang = new LittleMasterKang();
             director.BuidFood(kang);
             Food food = kang.BuildFood();
             food.ShowFood();
             Console.WriteLine();
             //创建大份量鸡蛋面建造者 康师傅
             MasterKang k = new MasterKang();
             director.BuidFood(k);
             Food f = k.BuildFood();
             f.ShowFood();
             Console.Read();
         }
     }
 }

结果

总结

建造者模式类似于工厂模式,但又有所不同,建造者模式最主要的功能是基本方法的调用顺序的安排,这些基本方法已经实现,而工厂方法则重点是创建,组装顺序则不关心。 使用场景

一是产品类非常复杂,或者产品类中调用顺序不同会产生不同的效果。

二是在对象创建过程中会使用到系统中的一些其他对象这些对象在产品对象的创建过程中不容易得到