设计模式之建造者模式(C#版本)
简介
建造这种行为,在生活中是无处不在的,比如建造一栋高楼,建造一辆车,建造一艘船等等。
在建造过程中,其实都有一定的流程或者说操作。拿车来举个例子吧,建造一辆车大概会需要制造车架、烤漆、放入引擎、内饰装配等等的步骤(对车的制造不太了解,只能乱吹一下🤨),而最终制造出来车辆的差异,往往是各个详细步骤中操作不一样而导致的。比如烤漆,选用什么颜色,烤多久,引擎用什么引擎,内饰是用真皮的还是人造皮的。这也就是今天要说的建造者模式。
下面我们来看一下,如何打造一个完美的女朋友吧。
打造一个完美的女朋友
我们先来看看,女朋友拥有些什么属性吧。(这些属性肯定还满足不了你们的需求🧐)
public class Girlfriend
{
// 年龄
public int Age { get; set; }
// 身高
public int Height { get; set; }
// 尺寸
public string Size { get; set; }
// 脸型
public string FaceType { get; set; }
// 腰型
public string WaistType { get; set; }
// 体重
public int Weight { get; set; }
}
好了,下面来打造一下女朋友。
static void Main(string[] args)
{
Girlfriend smallGirlFriend = new Girlfriend()
{
Age = 20,
Height = 140,
Size="Small",
FaceType="瓜子脸",
WaistType = "水蛇腰",
Weight = 40
};
Girlfriend bigGirlFriend = new Girlfriend()
{
Age = 25,
Height = 160,
Size="Big",
FaceType="大脸",
WaistType = "水桶腰",
Weight = 80
};
}
这里我new了2种不同风格类型的女朋友(因为每个人的口味和喜好不太一样,所以就new了2种,任君选择😏)。
第一种,小鸟依人型😏,芳龄20,身高140cm,尺寸小(至于是什么size,就自由发挥啦),脸型是瓜子脸,腰型是水蛇腰,体重40kg。
第二种,稳重型(又稳又重的那种)🥶,芳龄25,身高160cm,尺寸大(天马行空),脸型是大脸,腰型是水桶腰,体重80kg。
我们在打造女朋友的时候呢,都需要设置女朋友的年龄、身高、尺寸、体重、脸型、腰型,而每个属性设置的不同,就得出了不同类型的女朋友。
现在有个问题,假如我要2个都是小鸟依人型的女朋友的话(其实我想要10个🤤),我需要怎么做?
static void Main(string[] args)
{
Girlfriend smallGirlFriend1 = new Girlfriend()
{
Age = 20,
Height = 140,
Size="Small",
FaceType="瓜子脸",
WaistType = "水蛇腰",
Weight = 40
};
Girlfriend bigGirlFriend2 = new Girlfriend()
{
Age = 20,
Height = 140,
Size="Small",
FaceType="瓜子脸",
WaistType = "水蛇腰",
Weight = 40
};
}
哦,简单啦,复制粘贴一下不就好了吗?看起来好像问题不大,但是重复的代码多了,如果,需要构造的对象,比这里的复杂得多的话,重复的代码将会更加地多,直接导致代码可阅读性降低(其实设计模式的根本目的,是让代码结构更清晰,更好地去阅读、理解和拓展)。
下面,该到建造者模式出场了。
先定义好打造完美女朋友的一个抽象类(将打造女朋友需要的过程先抽象出来)
public abstract class GrilfriendBuilder
{
protected Girlfriend _girlFriend = new Girlfriend ();
// 设置年龄
public abstract void SetAge();
// 设置身高
public abstract void SetHeight();
// 设置尺寸
public abstract void SetSize();
// 设置脸型
public abstract void SetFaceType();
// 设置腰型
public abstract void SetWaistType();
// 设置体重
public abstract void SetWeight();
// 获得女朋友
public abstract Girlfriend GetResult();
}
接着定义打造不同类型女朋友的实现类(实现打造女朋友的实际过程)
先是小鸟依人型的。
public class SmallGrilFriendBuilder : GrilfriendBuilder
{
public override Girlfriend GetResult()
{
return this._girlFriend;
}
public override void SetAge()
{
_girlFriend.Age = 20;
}
public override void SetFaceType()
{
_girlFriend.FaceType = "瓜子脸";
}
public override void SetHeight()
{
_girlFriend.Height = 140;
}
public override void SetSize()
{
_girlFriend.Size="Small";
}
public override void SetWaistType()
{
_girlFriend.WaistType = "水蛇腰";
}
public override void SetWeight()
{
_girlFriend.Weight = 40;
}
}
接着是稳重型的。
public class BigGirlFriendBuilder : GrilfriendBuilder
{
public override Girlfriend GetResult()
{
return this._girlFriend;
}
public override void SetAge()
{
_girlFriend.Age = 25;
}
public override void SetFaceType()
{
_girlFriend.FaceType = "大脸";
}
public override void SetHeight()
{
_girlFriend.Height = 160;
}
public override void SetSize()
{
_girlFriend.Size = "Big";
}
public override void SetWaistType()
{
_girlFriend.WaistType = "水桶腰";
}
public override void SetWeight()
{
_girlFriend.Weight = 80;
}
}
有了这些建造者之后,是不是就可以直接打造了呢?建造者只告诉了你建造过程需要的操作,但是,这些操作的顺序或者哪些操作是需要的,都还不知道。(比如我告诉你煎蛋需要把鸡蛋加入锅中、放油、煎熟等操作,但也需要知道,正确的步骤是先放油,接着将鸡蛋加入锅中,最后煎熟,那如果没有人告诉我正确步骤,可能会操作成先将鸡蛋煎熟之后才放油,再放鸡蛋的喔哈哈哈哈哈哈)所以,这里还需要一个告诉我们操作顺序和实际需要操作什么的人(指挥者)。
public class Director
{
// 女朋友建造者
private GrilfriendBuilder _builder;
public Director(GrilfriendBuilder builder)
{
this._builder = builder;
}
// 女朋友建造过程
public void Construct()
{
_builder.SetAge();
_builder.SetHeight();
_builder.SetSize();
_builder.SetFaceType();
_builder.SetWaistType();
_builder.SetWeight();
}
}
既然万事俱备了,我们再来打造一次女朋友吧。
static void Main(string[] args)
{
// 打造小鸟依人型女朋友
SmallGrilFriendBuilder smallGirlFriendBuilder = new SmallGrilFriendBuilder ();
Director director = new Director (smallGirlFriendBuilder);
director.Construct();
Girlfriend smallGirlfriend = smallGirlFriendBuilder.GetResult();
// 打造稳重型女朋友
BigGirlFriendBuilder bigGirlFriendBuilder = new BigGirlFriendBuilder ();
Director director1 = new Director (bigGirlFriendBuilder);
director1.Construct();
Girlfriend bigGirlfriend = bigGirlFriendBuilder.GetResult();
}
从代码中,可以看到指挥者还有一个作用,那就是隐藏建造的细节,让使用者不需要关心具体是如何实现的。
总结
建造者模式,通过将构造对象需要的过程进行抽象,让相同的构造过程可以创建不同的对象表示,同时,也隐藏了构造的实现过程。
建造者模式与工厂模式的区别在哪里?工厂模式只是返回需要的类型,比如之前文章说的,猫类还是狗类,但建造者模式,返回的是相同类型的不同描述(或者说是表示),比如这里返回的都是女朋友,只是女朋友会有身高、体重等不同属性描述。
好了,你会打造属于自己的完美女朋友了吗?🤔🤔🤔