标准 专业
多元 极客

设计模式实验室(18)——建造者模式

什么是建造模式?

建造者模式是一种对象创建型模式。

建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以构建不同的表示。

建造者模式广泛应用于生活中,比如我们去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();
		}
	}
}

模式总结

优点

  • 符合开闭原则。新增具体产品只需增加一个新的具体建造者外加一个指挥者即可,无需对以前的对象进行修改。
  • 可以更加精细的控制产品的创建过程,产品创建的步骤分布在不同的方法中,创建流程更加清晰,开发者可以更好的控制创建过程。
  • 获取产品和产品创建过程解耦,外部调用无需了解具体的创建过程。

缺点

  • 如果产品细分的比较明显,那么需要不断的新增指挥者类或者是具体建造者,增加了系统的复杂度和理解难度。
  • 设计难度高,建造者模式需要产品具有较多的相同点,这对系统设计者是一个考验。

适用场景

  • 相同的流程,相同点的产品。
  • 创建复杂对象的算法独立于对象的组成装配。
  • 产品对象的生成具有依赖关系,或者是需要更换生产步骤顺序。
赞(0) 投币

评论 抢沙发

慕勋的实验室慕勋的研究院

码字不容易,路过请投币

支付宝扫一扫

微信扫一扫