建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
那建造者模式到底是什么意思呢,按照惯例,我们还是运用生活中具体的例子来给大家讲解
比如我们现在要建造一栋房子,现实生活中造房子工序很复杂,为了简化,我们只有四道工序:建造墙(buildWall)、建造窗户(buildWindow)、建造门(buildDoor)和建造屋顶(buildRoof)。也就是说不管造什么样的房子,都是这四道工序或者是这四道中的几种(比如,可能有人想建造一栋密室,那么他就不需要窗户了),不能有这四道工序之外的其他工序。而不同房子之间的差异就是每道工序中用的建筑材料不一样,比如我要建造一间公寓(Apartment),那可能就会使用一般的材料,如果我想建造一栋高级别墅(Villa),那我可能就会选用高级一些的建筑材料。那么对于这种有相对固定的创建过程,只是在具体内容上有差异的对象,我们应该如何来创建他们呢,这正是建造者模式(Builder)要解答的问题。下面分析下在建造者模式中都有哪些具体的角色。
抽象产品角色(Abstract Product):明确规定了产品的构成,但对于每一部分的具体内容不做要求,比如:房子(有固定构成:墙、窗户、门和屋顶)
具体产品角色(Concrete Product):和抽象产品有同样的构成,但在每个构成上有不同的特点,比如:公寓和别墅
指挥者角色(Director):负责设计房子,由设计师决定要建造一栋什么样的房子,公寓还是别墅
抽象建造者角色(Abstract Builder):负责建造房子,他有相应的抽象方法:buildWall、buildWindow、buildDoor、buildRoof
具体建造者角色(Concrete Builder):具体负责建造房子的角色,实现抽象建造者的方法,建造具体产品,比如在我们的例子中,具体建造者角色就分为公寓建造者(ApartmentBuilder)和别墅建造者(VillaBuilder)
最后还有我们的客户角色(Client):雇用上面这个施工队建房子的人
需要说明的是,我们上面的角色组成应该是建造者模式中最全的角色组成了,读者在看其他同行们写的文章中可能会发现他们描述的建造者模式角色组成会简单的多,比如可能会省去抽象产品角色,抽象建造者角色,有的甚至会省去指挥者角色。需要告诉大家的是,设计模式是一种很灵活的设计思想,在不同应用中同一种设计模式会有不同的组成,这很正常,希望大家不要拘泥于形式,真正理解它的思想才是最重要的。
下面我们就用示例代码给大家演示一下建造者模式是怎么建造一间房子的:
抽象产品角色:房子(House)
package com.builder;
/*
* 抽象产品角色
*/
public abstract class House {
/*
* 四个方法,用来表现产品的四个构成部分
*/
public abstract void Wall();
public abstract void Window();
public abstract void Door();
public abstract void Roof();
public abstract void complete();
}
具体产品角色:公寓(Apartment)
package com.builder;
/*
* 具体产品角色
*/
public class Apartment extends House {
@Override
public void Door() {
System.out.println("公寓:正在建造普通三合板门");
}
@Override
public void Roof() {
System.out.println("公寓:正在建造普通屋顶");
}
@Override
public void Wall() {
System.out.println("公寓:正在建造一般砖墙");
}
@Override
public void Window() {
System.out.println("公寓:正在建造普通窗户");
}
@Override
public void complete() {
System.out.println("公寓:建造完成,耗时3个月");
}
}
具体产品角色:别墅(Villa)
package com.builder;
/*
* 具体产品角色
*/
public class Villa extends House {
@Override
public void Door() {
System.out.println("别墅:正在建造高级实木门");
}
@Override
public void Roof() {
System.out.println("别墅:正在建造高级屋顶");
}
@Override
public void Wall() {
System.out.println("别墅:正在建造高级大理石墙");
}
@Override
public void Window() {
System.out.println("别墅:正在建造高级铝合金窗户");
}
@Override
public void complete() {
System.out.println("別墅:建造完成,耗时6个月");
}
}
抽象建造者角色:建造者(Builder)
package com.builder;
/*
*抽象建造者角色
*/
public abstract class Builder {
/*
* 四个抽象方法,表示建造房子的四个步骤
*/
public abstract void builWall();
public abstract void builWindow();
public abstract void builDoor();
public abstract void builRoof();
/*
* 返回建造好的房子
*/
public abstract House getHouse();
}
具体建造者角色:公寓建造者(ApartmentBuilder)
package com.builder;
/*
* 具体建造者角色,负责建造公寓
*/
public class ApartmentBuilder extends Builder {
House apartment = new Apartment();
@Override
public void builDoor() {
apartment.Door();
}
@Override
public void builRoof() {
apartment.Roof();
}
@Override
public void builWall() {
apartment.Wall();
}
@Override
public void builWindow() {
apartment.Window();
}
@Override
public House getHouse() {
apartment.complete();
/*
* 将建好的公寓返回
*/
return apartment;
}
}
具体建造者角色:别墅建造者(VillaBuilder)
package com.builder;
/*
* 具体建造者角色,负责建造别墅
*/
public class VillaBuilder extends Builder {
House villa = new Villa();
@Override
public void builDoor() {
villa.Door();
}
@Override
public void builRoof() {
villa.Roof();
}
@Override
public void builWall() {
villa.Wall();
}
@Override
public void builWindow() {
villa.Window();
}
@Override
public House getHouse() {
villa.complete();
/*
* 将建好的别墅返回
*/
return villa;
}
}
指挥者角色:房子设计者(Director)
package com.builder;
public class Director {
Builder builder = null;
public Director(Builder builder) {
this.builder = builder;
}
public House builderHouse() {
builder.builDoor();
builder.builRoof();
builder.builWall();
builder.builWindow();
House house = builder.getHouse();
return house;
}
}
客户角色:房主(Client)
package com.builder;
public class Client {
public static void main(String[] args) {
House myHouse;
VillaBuilder villaBuilder = new VillaBuilder();
Director myDirector = new Director(villaBuilder);
/*
* 得到一个完整的房子
*/
myHouse = myDirector.builderHouse();
}
}
输出结果:
别墅:正在建造高级实木门
别墅:正在建造高级屋顶
别墅:正在建造高级大理石墙
别墅:正在建造高级铝合金窗户
別墅:建造完成,耗时6个月
各类之间的UML图如下:
这样当我们的客户类(Client)想要建造一座房子的时候,他只需要new一个Director,并告诉他想要一个什么样的房子,Director就会指挥他的施工队为客户建造一座具体的房子。
有的人会说,建造者模式看起来和我们之前讲过的工厂方法模式或者抽象工厂模式很像,对,这两个设计模式在一些内在原理上的确有很多相似的地方,建造者模式中的建造流程和抽象工厂模式中的产品系列其实是差不多的概念,建造者模式中的建造者角色和工厂方法模式中的工厂类也很相似。但是从具体概念上来说,工厂系列模式注重的是产品系列的创建,不关系产品内部细节,而建造者模式关心的是产品内部的构造流程和每个流程的内容,者一点正是两者的不同之处。
所以总的来讲,有一些设计模式之间其实是相通的,有些的确在一些基本原理上有些共同之处,但是既然会有这样一种设计模式出现,一定有它独特的应用场景和使用方法,而这正是我们所关心的,所以我觉得在学习设计模式的过程中,应该注重实际场景的应用,而不该拘泥于概念的理解。