一. 建造者模式基本介绍
在软件开发过程中有时需要创建一个"复杂的对象",该对象通常由多个子部件按一定的步骤聚合而成,其中各个部件的组合比较稳定或有一定的依赖次序,但各部件自身常面临着变化,这时可隔离出"复杂对象的各部分"的变化,从而保持系统中的"稳定构建算法"; 如邮件由发件人,收件人,主题,内容,附件组成。
1.定义
建造者模式(Builder Pattern)
-
它将一个复杂对象的构造与它的表示分离,可使使用者无需知道内部的组成细节,调用同样的构建过程可以创建不同的表示;
-
属于创建型设计模式,它将一个复杂对象分解为多个简单对象,然后一步步构建而成,
-
它将变与不变相分离,即产品的组成部分是不变的,但每部分是可以灵活选择的;
2.优点
-
客户端程序不必知道产品内部组成细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象;
-
不同建造者类对应着不同的对象构建的方法,因此若需要改变一个产品的内部表示,只需要换一个具体的建造者就可以了。
-
将复杂产品的创建步骤分解在不同方法中,使得创建过程更加清晰,从而使程序可以更加方便及精细的控制产品创建过程;
-
增加新的具体建造者无需修改原有类库的代码,指挥类针对抽象建造者类编程,系统扩展方便,符合"开闭原则";
3.缺点
-
产生多余的Build对象以及Director类;
-
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品间差异较大,则不适合使用该模式;
-
如果产品内部变换复杂,则可能导致需要定义很多具体建造者来实现这种变化,致使系统变得庞大,后期维护成本较大;
4.建造者模式和工厂模式的区别
-
建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
-
创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
-
关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成。
-
建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样。
二. 模式的应用场景
-
相同的构建过程(方法),不同的执行顺序,产生不同的事件结果时;
-
多个部件或零件,都可以装配到一个对象中,但产生的结果又不相同;
-
产品类非常复杂,参数多,而且很多参数都具有默认值;
-
在对象的创建过程中会使用到其他对象;
三. 建造者模式结构
客户端不必知道产品的内部组成细节,将产品本身与产品的创建过程解耦,使相同的创建过程可创建不同的产品对象;
-
把做一件事情所有的步骤作为抽象函数写到接口Builder中;
-
在实现类中重写所有抽象函数;
-
将建造者对象传递给指挥者,让指挥者依次执行所有的步骤;
-
通过Product的getProduct(),获取最后生成的对象。
1.模式结构图
2.建造者模式的角色分析:
1. Product(产品角色):是被构建的具体的产品对象,包含多个组成部分,具体建造者创建该产品的内部表示并定义它的装配过程;
2. Builder(抽象建造者): 负责指定建造产品相应流程的抽象方法:buildPartX():创建对象的各个部件 与 build():返回产品对象;
3. ConcreteBuilder(具体建造者): 实现Builder类指定的产品各个部件的具体构造方法和装配方法;
4. Director(指挥者): 调用Builder对象的部件构造与装配方法以控制产品的生产过程,完成对象的创建,隔离客户与产品生产过程;
3.模式的实现--建造房子
1.盖房项目需求
1>需要建房子,这一过程为打桩,砌墙,封顶;
2>房子有各种各样的,比如普通房,高楼,别墅,各种房子的过程虽然一样,但是要求各不相同;
3>请编写程序,完成需求;
2.实例结构图
3.相关代码实现
public class BuilderClient {
public static void main(String[] args) {
//该普通房
HighHouseBuilder commonHouse = new HighHouseBuilder();
//准备创建房子的指挥者
HouseDirector houseDirector = new HouseDirector(commonHouse);
//完成盖房子,返回产品(房子)
House house = houseDirector.constructHouse();
house.show(); //显示普通房子信息
System.out.println("------------------------------------------");
HighHouseBuilder houseBuilder = new HighHouseBuilder();
HouseDirector houseDirector2 = new HouseDirector(houseBuilder);
House house2 = houseDirector2.toBuildHouse();
house2.show();//显示高层房子信息
}
}
//指挥者处理类
public class HouseDirector {
HouseBuilder houseBuilder = null;
//构造器传入
public HouseDirector(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//通过setter方法 传入houseBuilder
public void setHouseBuilder(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//如何处理建造房子的流程,交给指挥者
public House toBuildHouse(){
return houseBuilder.buildHouse();
}
}
//产品--->Product
public class House {
private String basic;
private String wall;
private String roofed;
public String getBasic() {
return basic == null ? "" : basic;
}
public void setBasic(String basic) {
this.basic = basic;
}
public String getWall() {
return wall == null ? "" : wall;
}
public void setWall(String wall) {
this.wall = wall;
}
public String getRoofed() {
return roofed == null ? "" : roofed;
}
public void setRoofed(String roofed) {
this.roofed = roofed;
}
public void show(){
System.out.println(getBasic()+" ,"+getWall()+" ,"+getRoofed());
}
}
//抽象建造者
public abstract class HouseBuilder {
protected House house = new House();
//将建造的;流程写好,抽象方法
public abstract void buildBasic();//打地基
public abstract void buildWalls();//砌墙
public abstract void buildRoofed();//封顶
//建造房子
public House buildHouse() {
buildBasic();
buildWalls();
buildRoofed();
return house;
}
}
//具体建造者 普通楼
public class CommonHouseBuilder extends HouseBuilder {
@Override
public void buildBasic() { house.setBasic("给普通房子打地基5米"); }
@Override
public void buildWalls() {
house.setWall("给普通房子砌墙10cm");
}
@Override
public void buildRoofed() {
house.setRoofed("给普通房子封顶");
}
}
//具体建造者 高楼
public class HighHouseBuilder extends HouseBuilder {
@Override
public void buildBasic() { house.setBasic("给高楼打地基100米"); }
@Override
public void buildWalls() {
house.setWall("给高楼砌墙20cm");
}
@Override
public void buildRoofed() {
house.setRoofed("给高楼封顶");
}
}