Builder模式可以称为建造者模式,它将一个复杂对象的构建和表示分离,同样的构建过程可以创建不同的表示
适用场景:
相同的方法,不同执行顺序,产生不同事件结果
多个部件都可以装配到一个对象中,但产生的运行结果不相同
产品类非常复杂或者产品类因为调用顺序不同而产生不同作用
初始化一个对象时,参数过多,或者很多参数具有默认值
用 builder 模式创建共享单车为例子,示例代码: 没有贴出来的类请参考另外一篇文章 产品类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class Bike { private IFrame frame; private ISeat seat; private ITire tire; public IFrame getFrame () { return frame; } public void setFrame (IFrame frame) { this .frame = frame; } public ISeat getSeat () { return seat; } public void setSeat (ISeat seat) { this .seat = seat; } public ITire getTire () { return tire; } public void setTire (ITire tire) { this .tire = tire; } }
Builder 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 public abstract class Builder { abstract void buildFrame () ; abstract void buildSeat () ; abstract void buildTire () ; abstract Bike createBike () ; } public class MobikeBuilder extends Builder { private Bike mBike = new Bike(); @Override void buildFrame () { mBike.setFrame(new AlloyFrame()); } @Override void buildSeat () { mBike.setSeat(new DermisSeat()); } @Override void buildTire () { mBike.setTire(new SolidTire()); } @Override Bike createBike () { return mBike; } } public class OfoBuilder extends Builder { private Bike mBike = new Bike(); @Override void buildFrame () { mBike.setFrame(new CarbonFrame()); } @Override void buildSeat () { mBike.setSeat(new RubberSeat()); } @Override void buildTire () { mBike.setTire(new InflateTire()); } @Override Bike createBike () { return mBike; } }
导演类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Director { private Builder mBuilder = null ; public Director (Builder builder) { mBuilder = builder; } public Bike construct () { mBuilder.buildFrame(); mBuilder.buildSeat(); mBuilder.buildTire(); return mBuilder.createBike(); } }
使用方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Click { public static void main (String[] args) { showBike(new OfoBuilder()); showBike(new MobikeBuilder()); } private void showBike (Builder builder) { Director director = new Director(builder); Bike bike = director.construct(); bike.getFrame().frame(); bike.getSeat().seat(); bike.getTire().tire(); } }
上面示例是 Builder模式的常规用法,导演类 Director
在 Builder模式中具有很重要的作用,它用于指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,但是有些情况下需要简化系统结构,可以把Director和抽象建造者进行结合,示例代码: 改造后的抽象建造者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public abstract class NewBuilder { abstract void buildFrame () ; abstract void buildSeat () ; abstract void buildTire () ; abstract Bike createBike () ; public Bike construct () { this .buildFrame(); this .buildSeat(); this .buildTire(); return this .createBike(); } }
这样做确实简化了系统结构,但同时也加重了抽象建造者类的职责,也不是太符合单一职责原则,如果 construct()
过于复杂,建议还是封装到 Director
中
除了上面的用途外,还有另外一个常用的使用方式,就是当一个类构造器需要传入很多参数时,如果创建这个类的实例,代码可读性会非常差,而且很容易引入错误,此时就可以利用 builder模式进行重构,重构前示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Computer { private String cpu; private String screen; private String memory; private String mainboard; public Computer (String cpu, String screen, String memory, String mainboard) { this .cpu = cpu; this .screen = screen; this .memory = memory; this .mainboard = mainboard; } }
重构后示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class NewComputer { private String cpu; private String screen; private String memory; private String mainboard; public NewComputer () { throw new RuntimeException("can't init" ); } private NewComputer (Builder builder) { cpu = builder.cpu; screen = builder.screen; memory = builder.memory; mainboard = builder.mainboard; } public static final class Builder { private String cpu; private String screen; private String memory; private String mainboard; public Builder () {} public Builder cpu (String val) { cpu = val; return this ; } public Builder screen (String val) { screen = val; return this ; } public Builder memory (String val) { memory = val; return this ; } public Builder mainboard (String val) { mainboard = val; return this ; } public NewComputer build () {return new NewComputer(this );} } }
客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Click { public static void main (String[] args) { Computer computer = new Computer("cpu" , "screen" , "memory" , "mainboard" ); NewComputer newComputer = new NewComputer.Builder() .cpu("cpu" ) .screen("screen" ) .memory("memory" ) .mainboard("mainboard" ) .build(); } }
上面的示例代码只是传入四个参数,如果参数是十四个甚至更多,builder 模式的优势将会更加明显,传递参数更加灵活,代码具有更高的可读性
建造者模式与抽象工厂模式的比较:
与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族
在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象
如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车
说了这么多 Builder模式的好处,再来看看它有什么缺点:
Builder模式所创建的产品一般具有较多共同点,组成部分也相似,所以 Builder模式不适合创建差异性很大的产品类
产品内部变化复杂,会导致需要定义很多具体建造者类实现变化,增加项目中类的数量,增加系统的理解难度和运行成本
源码戳这里
评论