一、定义
官方定义:将一个复杂对象的构建和表示分离,使同样的构建过程可以创建不同的表示。
官方定义真的是....,好吧,让我来指点迷津。
二、建造者需要的几个角色
1.Product产品类。这个产品类比较复杂,内部有许多其它类的对象的引用,可以视为此产品类的逻辑上必不可少的“组成部分”。当我们要构造出此产品的时候,产品持有的其它引用也必须得到初始化。
2.Builder建造者。这是一个抽象接口,用于定义生产产品的各个“组成部分”。
3.ConcreteBuilder建造者实现类。具体生产出产品对象的各个组成部分。
4.Director指挥者。调用建造者实现类来生产出产品的各个组成部分,并将其装配到产品类中。
三、建造模式心法
建造模式与工厂模式十分相似。
区别在于:
工厂模式关心的是“生产出来的产品”,对于其构造过程的顺序不关心。
建造者设计模式强调的是构造顺序,它对于产品的构造过程有着合理的顺序控制,这好比Spring有顺序的注入合作者Bean一样。不同的构造顺序,可能生产出不同的产品。
现在可以解释官方的定义:将一个复杂对象的构建(产品复杂的构造过程)和表示(用户拿到的产品对象的地方,或者说是能够进行调用产品对象的环境)分离,使同样的构建过程(抽象建造者定义的统一接口,Builder类的意思)可以创建不同的表示(不同的具体建造者,产生不同的产品)。简单说:让调用环境与产品复杂的构造逻辑解耦。
现在的效果就是,在客户端拿到的产品,它是怎么创建的,我们不知道。如果我们想手动创建产品,那么将会出现下面的代码:先Product product = new Product(); product.setA();product.setB();......product.setL();这样代码又多又长。更加糟糕的是,如果需求变了,使用到product的地方都要修改set方法,难怪要加班啊。欲哭无泪。
如果是Product product = Director.getProduct(具体建造者类);即使需求变了,只需要修改具体建造者类的代码。因此,在我们的调用环境中,避免了与产品的复杂构造逻辑耦合,是建造者模式的一大好处。
四、例子
推荐一个无法超越的经典例子:建造者模式,作者:汉森X
下面的例子是我自己写的,很烂,推荐看推荐的经典例子。
public class Person {
private String Coat;//外套
private String jeans;//牛仔裤
private String shoes;//鞋子
public Person() {
}
public void setCoat(String coat) {
Coat = coat;
}
public void setJeans(String jeans) {
this.jeans = jeans;
}
public void setShoes(String shoes) {
this.shoes = shoes;
}
@Override
public String toString() {
return "Person{" +
"Coat='" + Coat + '\'' +
", jeans='" + jeans + '\'' +
", shoes='" + shoes + '\'' +
'}';
}
}
//建造者接口Builder,可以视为抽象的衣橱,提供衣服
interface Builder{
String provideCoat();
String provideJeans();
String provideShoes();
}
//构造者实现类。可以视为具体衣橱,比如自己家里面的衣橱
class ConcreteBuilder implements Builder{
@Override
public String provideCoat() {
return "霸气外套";
}
@Override
public String provideJeans() {
return "七匹狼牛仔裤";
}
@Override
public String provideShoes() {
return "耐克鞋子";
}
}
class Director{
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Person getPerson(){
Person person = new Person();
person.setCoat(builder.provideCoat());
person.setJeans(builder.provideJeans());
person.setShoes(builder.provideShoes());
return person;
}
//主函数视为调用环境,比如Controller中,或者是Service中
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Person person = director.getPerson();
System.out.println(person);//Person{Coat='霸气外套', jeans='七匹狼牛仔裤', shoes='耐克鞋子'}
}
}
五、优缺点
优点:
1.建造者模式有效的隐藏了类的构造过程,这个过程转由专门的类来提供实现,避免在客户端环境中与产品类复杂的构造逻辑耦合。
2.建造者模式是将产品复杂的构造过程封装在内部,对于外部调用的人来说,只需要传入建造者Director和建造工具ConcreteBuilder,对于内部是如何建造成成品的,调用者无需关心。
3.具体的建造者类逻辑独立,既可以创建新的建造者,又能在修改特定建造者类的同时,不影响其它建造者类,符合开放闭合原则。
缺点:
类比较多,代码开发量变大。解决方案是,我们可以在具体的建造者类中加入返回产品的方法,这就意味着,Director类将被删除,它的“按顺序装配产品与返回具体产品”的两个功能直接由具体建造者来提供。
分割线--------------------------------------------------------------------------------------------
下一篇:原型设计模式7