1、建造者模式
在前面我们讲到工厂模式,工厂模式的重点是封装了对象的创建,用户需要什么对象(产品),就给用户创建什么对象(产品),并不关心产品的组装顺序。比如我们在抽象工厂模式中的:要构建高端比亚迪,就获取高端比亚迪工厂;要构建低端比亚迪,就获取低端比亚迪工厂。那有一天客户需要中等比亚迪呢?
中等比亚迪型号1(高端发动机、低端座椅、低端轮胎);
中等比亚迪型号2(高端发动机、高端座椅、低端轮胎);
中等比亚迪型号3(低端发动机、高端座椅、高端轮胎);
....
客户的需求是多变的,如果要为每种型号都提供一个工厂,那工厂太多了。这个时候我们就可以通过建造者模式根据用户的选择来定制产品。
1.1、什么是建造者模式
- 定义:是一种创建型模式,可让您逐步构建复杂的对象。将一个复杂的对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
什么意思呢?我们先来看下实现建造者模式的一个结构。建造者(Builder)模式由抽象建造者、具体建造者、
产品、导向器等 4 个要素构成。
一般端直接和Director导向器沟通,通过向Director传入不同的ConcreteBuilder(具体建造者)构建不同表示的Product(产品)。
所以建造者模式把对象的构建(由Builder的实现来负责的)和装配(由Director负责的)进行了解耦,不同的构建器,相同的装配,也可以做出不同的产品。
1.2、模式的优缺点
- 优点
1)可以逐步构建对象、延迟构建步骤,将构建和表示分离;
2)各个具体的建造者相互独立,您可以重用相同的构建代码;
- 缺点
产品的组成部分必须相同,这限制了其使用范围,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
1.3、创建的方式
首先创建抽象建造者;
//1)抽象建造者
public interface Builder {
void setTyre(Tyre tyre);
void setSeat(Seat seat);
void setEngine(Engine engine);
}
class Tyre{
private String tyreVersion;
public Tyre(){
this.tyreVersion="入门级轮胎,寿命5年";
}
public Tyre(String tyreVersion) {
this.tyreVersion = tyreVersion;
}
public String getTyreVersion() {
return tyreVersion;
}
}
class Seat{
private String SeatVersion;
public Seat(){
this.SeatVersion="普通座椅";
}
public Seat(String seatVersion) {
SeatVersion = seatVersion;
}
public String getSeatVersion() {
return SeatVersion;
}
}
class Engine{
private String EngineVersion;
public Engine(){
this.EngineVersion="普通发动机";
}
public Engine(String engineVersion) {
EngineVersion = engineVersion;
}
public String getEngineVersion() {
return EngineVersion;
}
}
然后再创建实际建造者及产品;
//2)实际建造者
public class BydBuilder implements Builder {
private Tyre tyre;
private Seat seat;
private Engine engine;
@Override
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
public void setSeat(Seat seat) {
this.seat = seat;
}
@Override
public void setTyre(Tyre tyre) {
this.tyre = tyre;
}
//得到产品
public BydCar getMyBydCar(){
return new BydCar(tyre, seat, engine);
}
}
class BydCar{
private Tyre tyre;
private Seat seat;
private Engine engine;
public BydCar(Tyre tyre,Seat seat,Engine engine){
this.tyre = tyre;
this.seat = seat;
this.engine = engine;
System.out.println(this.toString());
}
public Tyre getTyre() {
return tyre;
}
public Seat getSeat() {
return seat;
}
public Engine getEngine() {
return engine;
}
@Override
public String toString() {
return this.engine.getEngineVersion()+"+"+
this.tyre.getTyreVersion()+"+"+
this.seat.getSeatVersion();
}
}
再创建导向器
//3)创建导向器
public class Director {
public void highBydCar(Builder builder){
builder.setEngine(new Engine("高端发动机"));
builder.setTyre(new Tyre("高端轮胎,可用10年"));
builder.setSeat(new Seat("高端真皮座椅"));
}
public void lowBydCar(Builder builder){
builder.setEngine(new Engine());
builder.setTyre(new Tyre());
builder.setSeat(new Seat());
}
//目前预售中端款比亚迪
public void MiddleBydCar(Builder builder){
builder.setEngine(new Engine("高端发动机"));
builder.setTyre(new Tyre()); //低端轮胎
builder.setSeat(new Seat()); //低端座椅
}
}
最后就是我们的客户端调用者。
public class Client {
public static void main(String[] args) {
//导向器
Director director = new Director();
//建造者
BydBuilder builder = new BydBuilder();
//产品
System.out.println("顾客1,看中了高端比亚迪");
director.highBydCar(builder);
builder.getMyBydCar();
System.out.println("顾客2,看中了低端比亚迪");
director.lowBydCar(builder);
builder.getMyBydCar();
System.out.println("顾客3,看中了中端比亚迪");
director.MiddleBydCar(builder);
builder.getMyBydCar();
System.out.println("顾客4,希望按照自己的意愿定制比亚迪");
builder.setEngine(new Engine("高端发动机"));
builder.setSeat(new Seat("高端座椅"));
builder.setTyre(new Tyre());//低端轮胎
builder.getMyBydCar();
}
}
案例执行效果:
案例中不仅仅有导向器中提供给使用者的一些产品,还支持使用者定制自己的产品。
1.4、总结及建议
建造者模式实现了构建和装配的解耦,不同的构建器,相同的装配,可以做出不同的产品对象;相同的构建器不同的装配顺序也可以做出不同的产品对象。
应用场景:
- 相同的方法,不同的执行顺序,产生不同的结果。
- 产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
- 初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
DJK中建造者模式的使用:
- java.lang.StringBuilder#append() (unsynchronized)
- java.lang.StringBuffer#append() (synchronized)
- java.nio.ByteBuffer#put()
- javax.swing.GroupLayout.Group#addComponent()