建造者模式(Builder Pattern): 将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示.
设计模式-概述
当有一个复杂对象需要构造, 对象内部各个组件均有很多平级配置, 构建者并不关心组件的内部结构, 此时使用建造者模式能很好的解决这种问题. 例如组装一个高达, 主要组成有:头部,身体,四肢. 这三个具体组成并不关心, 是个完整的头, 身体, 四肢就行了, 并且头部可能有各种颜色的, 身体,四肢也有各种不同的, 将会有不同的组合, 使用已有的组合将会是封闭的, 新增组合会是开放的, 符合”开闭原则”.
结构 组成部分为:
Builder : 抽象建造者
ConcreteBuilder : 具体建造者
Director : 指挥者
Product : 产品
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 @startuml builder-1 !include common.cuml Class(Product,"产品") { } Interface(Builder,"抽象建造者") { + setPart1() : void + setPart2() : void + setPart3() : void + getResult() : void } Class(ConcreteBuilder,"具体建造者") { + setPart1() : void + setPart2() : void + setPart3() : void + getResult() : void } Class(Director,"指挥者") { - builder : Builder + setBuilder() : void + buildProduct() : Product } Director o-right- Builder Builder <|... ConcreteBuilder ConcreteBuilder .up.> Product @enduml
使用时序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @startuml builder-2 actor 用户 as U participant Director as D participant ConcreteBuilder as C U --> C : <<create>> 我要用这个创建产品 U -> D : setBuilder(builder) U -> D : buildProduct() : Product activate D D -> C : setPart1() D -> C : setPart2() D -> C : setPart3() D -> C : getResult() D -> U : 收到ConcreteBuilder创建的Product deactivate D @enduml
代码实现 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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 public class Main { public static void main (String[] args) { Builder builder = new ConcreteBuilder (); Director director = new Director (); director.setBuilder(builder); Product product = director.buildProduct(); System.out.println(product.desc()); } } class Product { private String part1; private String part2; private String part3; Product(String part1, String part2, String part3) { this .part1 = part1; this .part2 = part2; this .part3 = part3; } public String desc () { return "产品这个样子:" + part1 + "_" + part2 + "_" + part3; } } interface Builder { void setPart1 () ; void setPart2 () ; void setPart3 () ; Product getResult () ; } class ConcreteBuilder implements Builder { private String part1; private String part2; private String part3; @Override public void setPart1 () { System.out.println("安装组件1" ); this .part1 = "组件1" ; } @Override public void setPart2 () { System.out.println("安装组件2" ); this .part2 = "组件2" ; } @Override public void setPart3 () { System.out.println("安装组件3" ); this .part3 = "组件3" ; } @Override public Product getResult () { return new Product (part1, part2, part3); } } class Director { private Builder builder; public void setBuilder (Builder builder) { this .builder = builder; } Product buildProduct () { builder.setPart1(); builder.setPart2(); builder.setPart3(); return builder.getResult(); } }
使用场景
生成的产品有复杂的结构, 各个成员间性质差别明确.
属性之间可能有联系, 可能有特定的生成顺序.
隔离复杂对象的创建和使用, 并使得相同的创建过程可以创建不同的产品, 仅需要实现建造者接口即可.
具体应用
protobuf 对象的创建使用了建造者模式(变种)
1 2 3 4 SimpleRequest.Builder builder = SimpleRequest.newBuilder(); builder.setId(12341 ); builder.setName("你好" ); SimpleRequest request = builder.build();
Android 中AlertDialog使用
1 2 3 4 5 new AlertDialog .Builder(this ) .setCancelable(true ) .setIcon(R.mipmap.app_logo) .setMessage("温馨提醒" ) .show();