建造者模式的定义是:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。本质就是将共同的构造方法高度提炼形成所有对象共有,这样的话不同达到一个方法在不同调用场景下产生不同对象(总流程不变变得只是代码实现)。
使用场景:
楼房是千差万别的,楼房的外形,层数,内部房间的数量,房间的装饰都不一样。但是对于建造者来说,抽象出来的建筑流程是确定的。因为建筑一座楼房,都可以归纳为几个步骤:1打桩、2建地基、3搭框架、4内部建设。同理,建造者设计模式也是基于这样的概念而生的,这个设计模式用来解决什么样的情况呢:即流程不变,但每个流程实现的具体细节是会变化的。这样的情况,可以考虑使用建造者。就像盖房子,4个流程都必须有,但每个流程各自的实现细节,各个房子各有不同。建造者模式的好处就是保证了流程不会变化,即流程不会增加也不会遗漏,也不会产生流程次序的错误。这是非常重要的,看新闻,一些楼歪歪的事件,很多都是建设楼盘的时候,流程出现了问题导致的。(看来这些人并不知道建造者模式啊)。而建造者模式,保证了流程的确定性,而流程内部的实现细节,是可继承扩展的。从根源上解决了流程不规范的问题。
代码走起:
业务场景:
每个人一生中都要经历婴儿、童年、少年、中年、老年的人生阶段。这是无法逃避的不同的是每个人生命体验不同罢了,用建造者模式来设计的话婴儿、童年、少年、中年、老年是固定不变的变得是不同人来经历。看如下代码:
首先创建人生长历程抽象类
/// <summary>
/// 人的成长历程抽象类---
/// </summary>
public interface IPersonGrowthProcess
{
/// <summary>
/// 宝宝
/// </summary>
void Baby();
/// <summary>
/// 儿童时代
/// </summary>
void Children();
/// <summary>
/// 少年时代
/// </summary>
void Young();
/// <summary>
/// 中年时代
/// </summary>
void MiddleAged();
/// <summary>
/// 老年时代
/// </summary>
void OldPerson();
}
看实现该接口的白人类和黄种人类
/// <summary>
/// 黄种人生活历程
/// </summary>
public class YellowPersonGrowthProcess : IPersonGrowthProcess
{
/// <summary>
///
/// </summary>
public void Baby()
{
Console.WriteLine("我是生活在亚洲的黄种人Person");
Console.WriteLine("我和其他肤色的Person都要经历Baby时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void Children()
{
Console.WriteLine("我是生活在亚洲的黄种人Person");
Console.WriteLine("我和其他肤色的Person都要经历Children时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void Young()
{
Console.WriteLine("我是生活在亚洲的黄种人Person");
Console.WriteLine("我和其他肤色的Person都要经历Young时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void MiddleAged()
{
Console.WriteLine("我是生活在亚洲的黄种人Person");
Console.WriteLine("我和其他肤色的Person都要经历MiddleAged时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void OldPerson()
{
Console.WriteLine("我是生活在亚洲的黄种人Person");
Console.WriteLine("我和其他肤色的Person都要经历OldPerson时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
}
/// <summary>
/// 白种人生活历程
/// </summary>
public class WhitePersonGrowthProcess : IPersonGrowthProcess
{
/// <summary>
///
/// </summary>
public void Baby()
{
Console.WriteLine("我是生活在欧洲的白种人Person");
Console.WriteLine("我和其他肤色的Person都要经历Baby时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void Children()
{
Console.WriteLine("我是生活在欧洲的白种人Person");
Console.WriteLine("我和其他肤色的Person都要经历Children时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void Young()
{
Console.WriteLine("我是生活在欧洲的白种人Person");
Console.WriteLine("我和其他肤色的Person都要经历Young时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void MiddleAged()
{
Console.WriteLine("我是生活在欧洲的白种人Person");
Console.WriteLine("我和其他肤色的Person都要经历MiddleAged时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
public void OldPerson()
{
Console.WriteLine("我是生活在欧洲的白种人Person");
Console.WriteLine("我和其他肤色的Person都要经历OldPerson时代但是不同点的是我和其他Person只是生活环境不同以及生活方式不同罢了");
}
}
具体业务逻辑:
/// <summary>
/// 人物展现
/// </summary>
public class PersonDirector
{
private IPersonGrowthProcess _personGrowthProcess = null;
public PersonDirector(IPersonGrowthProcess personGrowthProcess)
{
this._personGrowthProcess = personGrowthProcess;
}
/// <summary>
/// 任何Person都要尽力的生命历程
/// </summary>
public void ShowPersonGrowthProcess()
{
_personGrowthProcess.Baby();
_personGrowthProcess.Children();
_personGrowthProcess.Young();
_personGrowthProcess.MiddleAged();
_personGrowthProcess.OldPerson();
}
static void Main(string[] arge)
{
//白种人生活历程
IPersonGrowthProcess whitePersionGrowthProcess = new WhitePersonGrowthProcess();
PersonDirector persionDirector = new PersonDirector(whitePersionGrowthProcess);
persionDirector.ShowPersonGrowthProcess();
Console.WriteLine("---------------------其他肤色的人---------------------------");
//黄种人人生活历程
IPersonGrowthProcess yPersonGrowthProcess = new YellowPersonGrowthProcess();
PersonDirector ypersionDirector = new PersonDirector(yPersonGrowthProcess);
ypersionDirector.ShowPersonGrowthProcess();
Console.ReadLine();
}
}
运行结果:
上面的例子,通过建造者模式,使得建造过程通过PersonDirector类的Construct函数固定了,即建造过程不会变,但是具体的婴儿、童年、少年、中年、老年这些时期的各个部分会变化,基类IPersonGrowthProcess中将各种每个时期函数定义为抽象方法,必须在子类中实现。这样不仅仅使得经历各个时期的过程不变,而且很利于系统的扩展,一旦出现其他种类的人根本不需要改动之前的YellowPersonGrowthProcess,WhitePersonGrowthProcess等类,只需要新添加新的类。符合OCP原则。
使用建造者模式的好处:
1.使用建造者模式可以使客户端不必知道产品内部组成的细节。
2.具体的建造者类之间是相互独立的,对系统的扩展非常有利。
3.由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。