建造者模式可以说是对工厂模式的扩展,工厂类提供了生产单个产品的功能,而建造者模式则可以将各种产品集中起来进行统一管理。工厂模式关注的是整个产品,建造者模式关注的是产品各组成部分的创建过程。
比如要创建一辆车,你只关心汽车本身(之后加以使用),就用工厂模式创建;若还关注该汽车的各部分是怎么造出来的(或者不同的工厂对产品的各部分的造法不同,就用Builder)。如StringBuilder对字符串的整合,append()、delete()、insert()改变数据。
导演者角色是与客户端打交道的角色。导演者将客户端创建产品的请求划分为对各个零件的建造请求,再将这些请求委派给具体建造者角色。具体建造者角色是做具体建造工作的,但是却不为客户端所知。
一般来说,每有一个产品类,就有一个相应的具体建造者类。这些产品应当有一样数目的零件,而每有一个零件就相应地在所有的建造者角色里有一个建造方法。
角色Builder:
package com.deppon.tps.module.BuilderPatternTest;
/**
* 抽象建造者接口PersonBuilder(为创建一个产品对象的各个部件指定抽象接口)
* @author 284724
*/
public interface PersonBuilder {
void builderHead();
void builderBody();
void builderFoot();
Person BuilderPerson();
}
角色ConcreteBuilder:
package com.deppon.tps.module.BuilderPatternTest;
/**
* 具体建造者类ManBuilder
* @author 284724
*
*/
public class ManBuilder implements PersonBuilder{
Person person;
public ManBuilder(){
person=new Man();
}
public void builderHead(){
person.setHead("建造男人的头");
}
public void builderBody(){
person.setBody("建造男人的身体");
}
public void builderFoot(){
person.setFoot("建造男人的脚");
}
public Person BuilderPerson(){
return person;
}
}
角色ConcreteBuilder:
package com.deppon.tps.module.BuilderPatternTest;
/**
* 具体建造者类WomanBuilder
* @author 284724
*
*/
public class WomanBuilder implements PersonBuilder{
Person person;
public WomanBuilder() {
person=new Woman();
}
public void builderHead(){
person.setHead("建造女人的头");
}
public void builderBody(){
person.setBody("建造女人的身体");
}
public void builderFoot(){
person.setFoot("建造女人的脚");
}
public Person BuilderPerson(){
return person;
}
}
角色Director:
package com.deppon.tps.module.BuilderPatternTest;
/**
* 导演者类PersonDirector
* @author 284724
*
*/
public class PersonDirector {
public Person ConstructPerson(PersonBuilder pb){
pb.builderHead();
pb.builderBody();
pb.builderFoot();
return pb.BuilderPerson();
}
}
角色Product:
package com.deppon.tps.module.BuilderPatternTest;
public class Man extends Person{
public Man(){
System.out.println("开始建造男人");
}
}
package com.deppon.tps.module.BuilderPatternTest;
public class Woman extends Person{
public Woman(){
System.out.println("开始建造女人");
}
}
package com.deppon.tps.module.BuilderPatternTest;
public class Person {
private String head;
private String body;
private String foot;
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getFoot() {
return foot;
}
public void setFoot(String foot) {
this.foot = foot;
}
}
测试:
package com.deppon.tps.module.BuilderPatternTest;
public class Test {
public static void main(String[] arg){
PersonDirector personDirector=new PersonDirector();
Person manPerson=personDirector.ConstructPerson(new ManBuilder());
Person womanPerson=personDirector.ConstructPerson(new WomanBuilder());
System.out.println(manPerson.getHead());
System.out.println(manPerson.getBody());
System.out.println(manPerson.getFoot());
System.out.println(womanPerson.getHead());
System.out.println(womanPerson.getBody());
System.out.println(womanPerson.getFoot());
}
}
使用场景
假设有一个电子杂志系统,定期地向用户的电子邮件信箱发送电子杂志。用户可以通过网页订阅电子杂志,也可以通过网页结束订阅。当客户开始订阅时,系统发送一个电子邮件表示欢迎,当客户结束订阅时,系统发送一个电子邮件表示欢送。本例子就是这个系统负责发送“欢迎”和“欢送”邮件的模块。注: 这个例子里面各个产品类均有一个共同的接口如下:package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
import java.util.Date;
public class AutoMessage {
//收件人地址
private String to;
//发件人地址
private String from;
//主题
private String subject;
//内容
private String body;
//发送日期
private Date sendDate;
public void send(){
System.out.println("收件人地址:"+to);
System.out.println("发件人地址:"+from);
System.out.println("主题:"+subject);
System.out.println("内容:"+body);
System.out.println("发送日期:"+sendDate);
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Date getSendDate() {
return sendDate;
}
public void setSendDate(Date sendDate) {
this.sendDate = sendDate;
}
}
具体产品类WelcomeMessage
package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
public class WelcomeMessage extends AutoMessage{
public WelcomeMessage(){
System.out.println("发送欢迎信息");
}
}
具体产品类GoodbyeMessage
package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
public class GoodbyeMessage extends AutoMessage{
public GoodbyeMessage(){
System.out.println("发送欢送信息啦!");
}
}
抽象建造者类
package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
import java.util.Date;
public abstract class Builder {
protected AutoMessage msg;
public abstract void builderSubject();
public abstract void builderBody();
public void builderTo(String to){
msg.setTo(to);
}
public void builderFrom(String from){
msg.setFrom(from);
}
public void builderSendDate(){
msg.setSendDate(new Date());
}
public void sendMessage(){
msg.send();
}
}
具体建造者WelcomeBuilder
package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
public class WelcomeBuilder extends Builder{
public WelcomeBuilder(){
msg=new WelcomeMessage();
}
public void builderSubject(){
msg.setSubject("欢迎标题");
}
public void builderBody(){
msg.setBody("欢迎内容");
}
}
具体建造者GoodbyeBuilder
package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
public class GoodbyeBuilder extends Builder{
public GoodbyeBuilder(){
msg=new GoodbyeMessage();
}
@Override
public void builderSubject() {
msg.setSubject("欢送标题");
}
@Override
public void builderBody() {
msg.setBody("欢送内容");
}
}
导演者Director
package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
public class Director {
Builder builder;
public Director(Builder builder){
this.builder=builder;
}
public void construct(String toAdress,String fromAdress){
this.builder.builderTo(toAdress);
this.builder.builderFrom(fromAdress);
this.builder.builderSubject();
this.builder.builderBody();
this.builder.builderSendDate();
this.builder.sendMessage();
}
}
客户端Client
package com.deppon.tps.module.BuilderPatternTest.MessageBuilder;
public class Test {
public static void main(String[] arg){
Director director=new Director(new WelcomeBuilder());
director.construct("285457966@qq.com", "13966741558@qq.com");
director.construct("13966741558@qq.com", "285457966@qq.com");
}
}
测试结果:
收件人地址:285457966@qq.com
发件人地址:13966741558@qq.com
主题:欢迎标题
内容:欢迎内容
发送日期:Mon Nov 21 16:05:26 CST 2016
收件人地址:13966741558@qq.com
发件人地址:285457966@qq.com
主题:欢迎标题
内容:欢迎内容
发送日期:Mon Nov 21 16:05:27 CST 2016
建造模式分成两个很重要的部分:
1. 一个部分是Builder接口,这里是定义了如何构建各个部件,也就是知道每个部件功能如何实现,以及如何装配这些部件到产品中去;
2. 另外一个部分是Director,Director是知道如何组合来构建产品,也就是说Director负责整体的构建算法,而且通常是分步骤地来执行。
不管如何变化,建造模式都存在这么两个部分,一个部分是部件构造和产品装配,另一个部分是整体构建的算法。认识这点是很重要的,因为在建造模式中,强调的是固定整体构建的算法,而灵活扩展和切换部件的具体构造和产品装配的方式。
再直白点说,建造模式的重心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用。具体的构造实现可以很方便地扩展和切换,从而可以灵活地组合来构造出不同的产品对象。