设计模式 | 飞机票 |
---|---|
三大工厂模式 | 登机入口 |
策略模式 | 登机入口 |
委派模式 | 登机入口 |
模板方法模式 | 登机入口 |
观察者模式 | 登机入口 |
单例模式 | 登机入口 |
原型模式 | 登机入口 |
代理模式 | 登机入口 |
装饰者模式 | 登机入口 |
适配器模式 | 登机入口 |
建造者模式 | 登机入口 |
责任链模式 | 登机入口 |
享元模式 | 登机入口 |
组合模式 | 登机入口 |
门面模式 | 登机入口 |
桥接模式 | 登机入口 |
中介者模式 | 登机入口 |
迭代器模式 | 登机入口 |
状态模式 | 登机入口 |
解释器模式 | 登机入口 |
备忘录模式 | 登机入口 |
命令模式 | 登机入口 |
访问者模式 | 登机入口 |
软件设计7大原则和设计模式总结 | 登机入口 |
当我们创建一个复杂对象时,可能大家的第一反应就是使用工厂模式。但是如果构建一个对象非常复杂,而且有些比如说属性之类的是可选的,而且需要支持我们自己随意的动态搭配,那么这时候如果要用工厂设计模式就不太好实现了,所以这就需要配合我们的建造者模式来实现。
建造者模式(Builder Pattern)是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式属于创建型模式,对使用者而言,只需要指定需要建造的类型就可以获得对象,建造过程和细节不需要了解。
建造者模式的概念听上去有点抽象,但是实际上可以这么说,基本上大家都用过,只是可能自己不知道这就是建造者模式而已。后面分析jdk源码中的应用大家就会知道了
建造者模式的设计中,主要有4个角色。
我们先来看一个简单的建造者模式写法:
首先我们创建一个产品,我们以家庭作业为例,假设老师会根据每个不同基础的同学布置不同难度的题目为例
package com.zwx.design.pattern.builder;
/**
* 建造者模式-产品(Product)角色
*/
public class Homework {
private String easyQc;//简答题目
private String normalQc;//正常题目
private String MediumQc;//中等难度题目
private String HardQc;//困难题目
public String getEasyQc() {
return easyQc;
}
public void setEasyQc(String easyQc) {
this.easyQc = easyQc;
}
public String getNormalQc() {
return normalQc;
}
public void setNormalQc(String normalQc) {
this.normalQc = normalQc;
}
public String getMediumQc() {
return MediumQc;
}
public void setMediumQc(String mediumQc) {
MediumQc = mediumQc;
}
public String getHardQc() {
return HardQc;
}
public void setHardQc(String hardQc) {
HardQc = hardQc;
}
}
接下来再创建一个建造者,通过建造者来创建不同的产品
package com.zwx.design.pattern.builder.simple;
import com.zwx.design.pattern.builder.Homework;
/**
* 建造者模式-具体建造者(ConcreteBuilder)
*/
public class SimpleBuilder {
private Homework homework;
public SimpleBuilder(Homework homework) {
this.homework = homework;
}
public void buildEasyQc(String easyQc){
homework.setEasyQc(easyQc);
}
public void buildNormalQc(String normalQc){
homework.setNormalQc(normalQc);
}
public void buildMediumQc(String mediumQc){
homework.setMediumQc(mediumQc);
}
public void buildHardQc(String hardQc){
homework.setHardQc(hardQc);
}
public Homework build(){
return homework;
}
}
最后,通过调用者来构建不同的产品
package com.zwx.design.pattern.builder.simple;
import com.alibaba.fastjson.JSONObject;
import com.zwx.design.pattern.builder.Homework;
/**
* 建造者模式-调用者(Director)
*/
public class SimpleBuilderDirector {
public static void main(String[] args) {
SimpleBuilder simpleBuilder = new SimpleBuilder(new Homework());
simpleBuilder.buildEasyQc("简单题目");//1
simpleBuilder.buildNormalQc("标准难度题目");//2
simpleBuilder.buildMediumQc("中等难度题目");//3
simpleBuilder.buildHardQc("高难度题目");//4
Homework homework = simpleBuilder.build();
System.out.println(JSONObject.toJSONString(homework));
}
}
这就是一个简单的构造者模式写法,上面的1,2,3,4行代码可以只选择任意1个或者任意搭配的个数,从而创造出独立不同的产品。
这种写法虽然简单,但是因为不是面向抽象编程,导致扩展性不好,所以我们再继续看一下建造者模式标准的写法
产品类复用上面简单示例的产品类
创建一个抽象建造者:
package com.zwx.design.pattern.builder.standard;
import com.zwx.design.pattern.builder.Homework;
/**
* 建造者模式-抽象建造者(Builder)
*/
public abstract class HomeworkBuilder {
public abstract HomeworkBuilder buildEasyQc(String easyQc);
public abstract HomeworkBuilder buildNormalQc(String normalQc);
public abstract HomeworkBuilder buildMediumQc(String mediumQc);
public abstract HomeworkBuilder buildHardQc(String hardQc);
public abstract Homework build();
}
这个类定义了5个方法,前面4个是产品类,实际开发中可以任意定义,相当于一个方法就是一个产品中的某一个部分,然后最后一个方法就是返回一个构建好的产品。
创建一个实际的建造者角色类:
package com.zwx.design.pattern.builder.standard;
import com.zwx.design.pattern.builder.Homework;
/**
* 建造者模式-具体建造者(ConcreteBuilder)
*/
public class ConcreateBuilder extends HomeworkBuilder {
private Homework homework;
public ConcreateBuilder(Homework homework) {
this.homework = homework;
}
@Override
public HomeworkBuilder buildEasyQc(String easyQc) {
homework.setEasyQc(easyQc);
return this;
}
@Override
public HomeworkBuilder buildNormalQc(String normalQc) {
homework.setNormalQc(normalQc);
return this;
}
@Override
public HomeworkBuilder buildMediumQc(String mediumQc) {
homework.setMediumQc(mediumQc);
return this;
}
@Override
public HomeworkBuilder buildHardQc(String hardQc) {
homework.setHardQc(hardQc);
return this;
}
@Override
public Homework build() {
return homework;
}
}
这个类里面初始产品我们是通过构造器传进去,实际上也可以不传,通过其他方法初始化也是可以的,这个看需求或者个人喜好。
注意:每个创建部分产品最后的返回值返回的都是this,这样就可以实现链式写法,具体看下面的调用者写法
最后调用者来创建产品
package com.zwx.design.pattern.builder.standard;
import com.alibaba.fastjson.JSONObject;
import com.zwx.design.pattern.builder.Homework;
/**
* 建造者模式-调用者(Director)
*/
public class HomeworkDirector {
public static void main(String[] args) {
Homework homework = new Homework();
HomeworkBuilder homeworkBuilder = new ConcreateBuilder(homework);
homeworkBuilder.buildEasyQc("我是一道简单题目")
.buildNormalQc("我是一道标准难度题目")
.buildMediumQc("我是一道中等难度题目")
.buildHardQc("我是一道高难度题目");
homework = homeworkBuilder.build();
System.out.println(JSONObject.toJSONString(homework));
}
}
可以看到,这里不用和之前一样一行行去调用,直接通过链式写法一直往下build,最终调用build()方法返回完整的产品对象。
PS:很多地方的写法是把调用者根据不同组合封装起一个个方法供外界调用,这也是一种最严格标准的写法,只适合于排列组合较少结果的产品。如果有很多种搭配,还是目前这种写法比较合适,直接由使用者自己来选择搭配。
建造者模式适用于一个具有较多的零件的复杂产品创建过程,而且产品的各个组成零件还会经常发生变化或者说需要支持动态变化,但是零件的种类却总体稳定的场景:
建造者模式在源码中使用也很普遍:
建造者模式的优点有:
建造者模式的缺点有:
建造者模式优点类似于工厂模式,都是用来创建一个对象,但是他们还是有很大的区别,主要区别如下:
本文主要介绍了建造者模式及其在JDK和MyBatis等框架中的具体应用实现,设计模式下一篇,将会介绍责任链模式,责任链模式是一种非常重要的设计模式,应尽可能掌握并熟练使用。
请关注我,和孤狼一起学习进步。