什么是建造模式?
建造者模式是一种对象创建型模式。
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以构建不同的表示。
建造者模式广泛应用于生活中,比如我们去StarBucks买咖啡时,每一种类的咖啡都会经过基于磨豆、煮、拉花之类(笔者没去过这么高端的地方,写的有问题请见谅)的步骤,建造者模式就是把这些步骤都封装起来,当我们需要一杯咖啡的时候,通过建造者模式的执行步骤后,返回给我们的就是一杯完美的咖啡。
核心结构
- Builder。抽象建造者,一般实现是抽象类或者接口,主要负责声明产品构建步骤和返回产品两类方法。
- ConcreteBuilder。具体建造者,实现了抽象建造者中声明的方法,明确各个创建步骤以及返回具体的产品。
- Product。产品,具体建造者负责生产并提供的对象。
- Director。指挥者,主要负责产品生产步骤的执行顺序,通过调用具体建造者实现的生产步骤和提供产品的方法,完成产品的生产。
类图展示
代码分析
我们还是以消息推送为例,消息推送可以分为指定推送,地域推送和全量推送。
首先,我们需要顶一个产品类型,即我们需要推送的消息:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——产品角色
*/
public class Message {
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 操作系统
*/
private String os;
/**
* 推送方法
*/
private String method;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
}
所有的消息均需要通过建造者进行创建:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——抽象建造者
*/
public abstract class MessageBuilder {
protected Message message = new Message();
public abstract void buildTitle();
public abstract void buildContent();
public abstract void buildOs();
public abstract void buildMethod();
public Message message() {
return message();
}
}
根据需要推送的消息不同类型,我们分别需要以下三种消息建造者的实现。
指定推送消息建造者实现:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——具体建造者
*/
public class AppointMessageBuilder extends MessageBuilder {
@Override
public void buildTitle() {
System.out.println("the title of appoint message");
}
@Override
public void buildContent() {
System.out.println("the content of appoint message");
}
@Override
public void buildOs() {
System.out.println("the operate system of appoint message");
}
@Override
public void buildMethod() {
System.out.println("the push method of appoint message");
}
}
地域推送建造者实现:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——具体建造者
*/
public class DistrictMessageBuilder extends MessageBuilder {
@Override
public void buildTitle() {
System.out.println("the title of district message");
}
@Override
public void buildContent() {
System.out.println("the content of district message");
}
@Override
public void buildOs() {
System.out.println("the operate system of district message");
}
@Override
public void buildMethod() {
System.out.println("the push method of district message");
}
}
全量消息建造者实现:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——具体建造者
*/
public class FullAmountMessageBuilder extends MessageBuilder {
@Override
public void buildTitle() {
System.out.println("the title of full amount message");
}
@Override
public void buildContent() {
System.out.println("the content of full amount message");
}
@Override
public void buildOs() {
System.out.println("the operate system of full amount message");
}
@Override
public void buildMethod() {
System.out.println("the push method of full amount message");
}
}
接下来就需要定义建造的顺序,定义指挥者:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——指挥者
*/
public class Director {
private MessageBuilder messageBuilder;
public Director(MessageBuilder messageBuilder) {
this.messageBuilder = messageBuilder;
}
public MessageBuilder construct() {
messageBuilder.buildTitle();
messageBuilder.buildContent();
messageBuilder.buildOs();
messageBuilder.buildMethod();
return messageBuilder;
}
}
指挥者中默认声明了建造的顺序。
接下来就需要针对三种不同的消息建造实现,实现三种不同的建造顺序。
指定消息建造顺序:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——指挥者
*/
public class AppointDirector {
private AppointMessageBuilder appointMessageBuilder = new AppointMessageBuilder();
public AppointMessageBuilder construct() {
appointMessageBuilder.buildTitle();
appointMessageBuilder.buildContent();
appointMessageBuilder.buildOs();
appointMessageBuilder.buildMethod();
return appointMessageBuilder;
}
}
地域消息建造顺序:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——指挥者
*/
public class DistrictDirector {
private DistrictMessageBuilder districtMessageBuilder = new DistrictMessageBuilder();
public DistrictMessageBuilder construct() {
districtMessageBuilder.buildTitle();
districtMessageBuilder.buildContent();
districtMessageBuilder.buildOs();
districtMessageBuilder.buildMethod();
return districtMessageBuilder;
}
}
全量消息建造顺序:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式——指挥者
*/
public class FullAmountDiretor {
private FullAmountMessageBuilder fullAmountMessageBuilder = new FullAmountMessageBuilder();
public FullAmountMessageBuilder construct() {
fullAmountMessageBuilder.buildTitle();
fullAmountMessageBuilder.buildContent();
fullAmountMessageBuilder.buildOs();
fullAmountMessageBuilder.buildMethod();
return fullAmountMessageBuilder;
}
}
接下来是我们的测试用例:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/17 0017.
* 建造者模式测试
*/
public class builderTest {
public static void main(String[] args) {
buidlerTest();
}
private static void buidlerTest() {
try {
Director director = new Director(new FullAmountMessageBuilder());
director.construct();
director = new Director(new AppointMessageBuilder());
director.construct();
director = new Director(new DistrictMessageBuilder());
director.construct();
FullAmountDiretor fullAmountDiretor = new FullAmountDiretor();
AppointDirector appointDirector = new AppointDirector();
DistrictDirector districtDirector = new DistrictDirector();
fullAmountDiretor.construct();
appointDirector.construct();
districtDirector.construct();
} catch (Exception e) {
e.printStackTrace();
}
}
}
模式总结
优点
- 符合开闭原则。新增具体产品只需增加一个新的具体建造者外加一个指挥者即可,无需对以前的对象进行修改。
- 可以更加精细的控制产品的创建过程,产品创建的步骤分布在不同的方法中,创建流程更加清晰,开发者可以更好的控制创建过程。
- 获取产品和产品创建过程解耦,外部调用无需了解具体的创建过程。
缺点
- 如果产品细分的比较明显,那么需要不断的新增指挥者类或者是具体建造者,增加了系统的复杂度和理解难度。
- 设计难度高,建造者模式需要产品具有较多的相同点,这对系统设计者是一个考验。
适用场景
- 相同的流程,相同点的产品。
- 创建复杂对象的算法独立于对象的组成装配。
- 产品对象的生成具有依赖关系,或者是需要更换生产步骤顺序。