建造者模式介绍
建造者模式是一个在软件开发中经常使用到的设计模式,下面看下它的定义。
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
比如我们想要造一把guitar,不用去关注它复杂的制作过程,屏蔽了制造细节,只需要将相应的部件,比如琴弦,面板等放入“制造库”,然后让“制造库”给我们来完成,换到编程语言里面来也一样,如果我们需要构建一个复杂且需要很多处引用的对象,如果我们都手动去构建,那么代码将会变得十分凌乱,且到处都是冗余的代码,这显然是不合理的,而且如果在构造的过程中如果出现参数的缺失和不对应等情况,那么将会对功能产生影响。
建造者模式的优点
1.符合面向对象的封装原则,构成过程和最终表示完全分离。
2.避免了代码臃肿,冗余,出错几率,使用了建造者模式,在很大程度上减少了系统的耦合,因为实现细节都已经屏蔽,所以开发者不需要去自己构建。
建造者模式的缺点
1.如果构建的对象发生了大的变化,那么我们需要去修改内部代码,这样就增加一定的成本。
2.构建的对象是固定的,各组成成分都需要按照要求来进行,所以灵活度不高。
权衡是否使用建造者模式
从建造者模式的优缺点中我们可以看出建造者模式给我们带来了很多好处,但是也会产生一定的影响,所以我们在使用的时候要考虑是否有必要用,是否合适用,不要为了使用设计模式而去使用设计模式。
使用建造者模式
下面我们使用Java语言来实现一个制作一把Guitar的过程。
忽略很多细节,我们造一把吉他通常需要指板,琴弦,面板等,还需要选定尺寸,下面我们用Java语言来表示一下吉他的结构体。
public class Guitar {
//弦
private String guitarString;
//弦钮
private String stringButton;
//面板
private String panel;
//拾音器
private String pickup;
//尺寸
private float size;
//指板
private String fingerboard;
//省略get,set
}
如果我们不使用构造者模式,而是使用构造函数,那么将会是这样的
Guitar guitar = new Guitar("伊利克斯", "grover", "Marshall", "玫瑰木", 42, "巴西玫瑰木");
仔细思考一下,使用构造函数来构建对象有什么问题,可以看出,如果参数很多的情况下,那么会让人眼花缭乱,会出现参数错位问题,不利于我们开发和维护,下面我们使用建造者模式来创建对象。
创建一个建造者
public class GuitarBuilder {
Guitar guitar = new Guitar();
public GuitarBuilder guitarString(String guitarString) {
guitar.setGuitarString(guitarString);
return this;
}
public GuitarBuilder stringButton(String stringButton) {
guitar.setStringButton(stringButton);
return this;
}
public GuitarBuilder panel(String panel) {
guitar.setPanel(panel);
return this;
}
public GuitarBuilder pickup(String pickup) {
guitar.setPickup(pickup);
return this;
}
public GuitarBuilder size(float size) {
guitar.setSize(size);
return this;
}
public GuitarBuilder fingerboard(String fingerboard) {
guitar.setFingerboard(fingerboard);
return this;
}
public Guitar build() {
return guitar;
}
下面我们就直接可以构造了
Guitar guitar = new GuitarBuilder()
.guitarString("伊利克斯")
.stringButton("grover")
.pickup("Marshall")
.panel("玫瑰木")
.size(42)
.fingerboard("巴西玫瑰木")
.build();
不过从上面我们总感觉怪怪的,建了两个类,一个实体,一个构造者,我们再进行改造一下,放到一个类里,我们知道,静态变量和静态方法可以直接通过类名调用,好家伙,就用静态内部类了。
public class Guitar {
//弦
private String guitarString;
//弦钮
private String stringButton;
//面板
private String panel;
//拾音器
private String pickup;
//尺寸
private float size;
//指板
private String fingerboard;
public static class GuitarBuilder{
Guitar guitar = new Guitar();
public GuitarBuilder guitarString(String guitarString){
guitar.setGuitarString(guitarString);
return this;
}
public GuitarBuilder stringButton(String stringButton){
guitar.setStringButton(stringButton);
return this;
}
public GuitarBuilder panel(String panel){
guitar.setPanel(panel);
return this;
}
public GuitarBuilder pickup(String pickup){
guitar.setPickup(pickup);
return this;
}
public GuitarBuilder size(float size){
guitar.setSize(size);
return this;
}
public GuitarBuilder fingerboard(String fingerboard){
guitar.setFingerboard(fingerboard);
return this;
}
public Guitar build(){
return guitar;
}
}
//省略get,set
}
构建对象
Guitar guitar = new Guitar.GuitarBuilder()
.guitarString("伊利克斯")
.stringButton("grover")
.pickup("Marshall")
.panel("玫瑰木")
.size(42)
.fingerboard("巴西玫瑰木")
.build();
使用Lombok插件的@Builder注解构建对象
在Lombok插件中我们可以很方便的使用建造者模式,只需要加上@Builder注解便可,我们使用Lombok来实现
@Builder
public class Guitar {
//弦
private String guitarString;
//弦钮
private String stringButton;
//面板
private String panel;
//拾音器
private String pickup;
//尺寸
private float size;
//指板
private String fingerboard;
}
构建对象
Guitar guitar = Guitar.builder().guitarString("伊利克斯")
.stringButton("grover")
.pickup("Marshall")
.panel("玫瑰木")
.size(42)
.fingerboard("巴西玫瑰木")
.build();
建造者模式的使用场景
如果我们创建的对象不是那么复杂,那么我们可以使用工厂模式来创建,因为工厂模式和建造者模式的目标都是屏蔽对象的创建过程,不过工厂模式一般来说不会去创建太过于复杂的对象,如果要创建比较复杂的对象,那么考虑使用建造者模式。