建造者模式(Builder Pattern)
建造者模式(Builder Pattern)
- 定义:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
- 主要作用:
在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
用户只需要给出指定复杂对象的类型和内容;
建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)
-
解决的问题
- 方便用户创建复杂的对象(不需要知道实现过程)
- 代码复用性 & 封装性(将对象构建过程和细节进行封装 & 复用)
Demo:
示例:制作手机 & 买手机。
工厂(建造者模式):负责制作手机(组装过程和细节在工厂内)
手机购买者(客户):你只需要说出你需要的型号(对象的类型和内容),然后直接购买就可以使用了
(不需要知道手机是怎么组装制作出来的(电池、充电器等等))
Director (指挥者) → Builder(建造者)
↑
ConcreteBuilder (具体建造者) → Product(产品)
指挥者:用于构建一个使用Builder接口对象(主要作用:隔离了客户与对象生产过程;负责控制产品对象的生产过程)
建造者:声明了具体的建造者的公共接口
具体建造者:实现Builder接口来实现组件对象
产品:构建后的对象
模式:
- 指挥者(Director)直接和客户→进行需求沟通;
- 沟通后指挥者将客户创建产品的需求划分为各个部件的建造请求(Builder);
- 将各个部件的建造请求委派到具体的建造者(ConcreteBuilder);
- 各个具体建造者负责进行产品部件的构建;
- 最终构建成具体产品(Product)。
下面我们引用一个例子来解释一下构建者模式:
首先我们定义Product类,里面用一个List存储product对象的各个部分:
1 public class Product { 2 private List<String> parts = new ArrayList<String>(); 3 4 public void add(String partName){ 5 parts.add(partName); 6 } 7 8 public void show(){ 9 System.out.println("----产品创建----"); 10 for (String part : parts) { 11 System.out.println(part); 12 } 13 } 14 }
我们定义Builder抽象类,并定义Product包括partA,partB,partC三个部分:
1 public abstract class Builder { 2 protected abstract void buildPartA(); 3 protected abstract void buildPartB(); 4 protected abstract void buildPartC(); 5 6 protected abstract Product getResult(); 7 }
分别定义ConcreateBuilder角色的BuilderA及BuilderB:
1 public class BuilderA extends Builder { 2 private Product product = new Product(); 3 4 @Override 5 protected void buildPartA() { 6 product.add("partA"); 7 } 8 9 @Override 10 protected void buildPartB() { 11 product.add("partB"); 12 } 13 14 @Override 15 protected void buildPartC() { 16 product.add("partC"); 17 } 18 19 @Override 20 protected Product getResult() { 21 return product; 22 } 23 }
1 public class BuilderB extends Builder { 2 private Product product = new Product(); 3 4 @Override 5 protected void buildPartA() { 6 product.add("partX"); 7 } 8 9 @Override 10 protected void buildPartB() { 11 product.add("partY"); 12 } 13 14 @Override 15 protected void buildPartC() { 16 product.add("partZ"); 17 } 18 19 @Override 20 protected Product getResult() { 21 return product; 22 } 23 }
现在,我们定义指导者角色BuilderDirector,在类中添加Builder的引用,并通过其构造方法初始化builder属性:
1 public class BuilderDirector { 2 3 private Builder builder = null; 4 5 public BuilderDirector(Builder builder){ 6 this.builder = builder; 7 } 8 9 public Product build(){ 10 builder.buildPartA(); 11 builder.buildPartB(); 12 builder.buildPartC(); 13 return builder.getResult(); 14 } 15 16 }
测试类:
1 public class BuilderTest { 2 3 public static void main(String[] args) { 4 5 BuilderDirector director = new BuilderDirector(new BuilderB()); 6 Product product = director.build(); 7 product.show(); 8 } 9 10 }
优缺点
-
优点
- 易于解耦
将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。
-
- 易于控制对象的创建
将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰。
-
- 方便拓展
增加新的具体建造者无需修改原有类库的代码,易于拓展。
具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响
- 缺点:
-
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
运用场景:
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;
- 创建一些复杂对象时,这些对象的内部组成部分之间的建造顺序是稳定的,但对象的内部组成构建面临着复杂的变化