1、建造模式涉及到4个角色:
抽象建造者角色(Builder):给出一个抽象接口,以规范产品对象的各个组成成分的建造。
要求的两种方法:一种是建造方法(buildPart1和 buildPart2),另一种是返还结构方法(retrieveResult)。
一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少 零件,就有多少相应的建造方法。
具体建造者角色(ConcreteBuilder):担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。
这个角色要完成的任务包括:
1.实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作。
2.在建造过程完成后,提供产品的实例。
导演者角色(Director):担任这个角色的类调用具体建造者角色以创建产品对象。
应当指出的是,导演者角色并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者角色。
产品角色(Product):产品便是建造中的复杂对象。
一般来说,一个系统中会有多于一个的产品类,而且这些产品类并不一定有共同的接口,而完全可以是不相关联的。
2、代码演示:
public class Product {
/**
* 定义一些关于产品的操作
*/
private String part1;
private String part2;
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
}
b.抽象建造者类Builder
public interface Builder {
//定义一些需要建造的方法
public void buildPart1();
public void buildPart2();
public Product retrieveResult();
}
c.具体建造者类ConcreteBuilder(具体干活的类)
public class ConcreteBuilder implements Builder {
private Product product = new Product();
/**
* 产品零件建造方法1
*/
@Override
public void buildPart1() {
//构建产品的第一个零件
product.setPart1("编号:9527");
}
/**
* 产品零件建造方法2
*/
@Override
public void buildPart2() {
//构建产品的第二个零件
product.setPart2("名称:XXX");
}
/**
* 产品返还方法
*/
@Override
public Product retrieveResult() {
return product;
}
}
d.导演者类Director
public class Director {
/**
* 持有当前需要使用的建造器对象
*/
private Builder builder;
/**
* 构造方法,传入建造器对象
* @param builder 建造器对象
*/
public Director(Builder builder){
this.builder = builder;
}
/**
* 产品构造方法,负责调用各个零件建造方法
*/
public void construct(){
builder.buildPart1();
builder.buildPart2();
}
}
e.使用
public class Client {
public static void main(String[]args){
Builder builder = new ConcreteBuilder();//new 一个具体的建造者类
Director director = new Director(builder);//new一个导演者类
director.construct();//执行具体的建造方法,开始建造
Product product = builder.retrieveResult();//拿到建造号的产品
System.out.println(product.getPart1());
System.out.println(product.getPart2());
}
}
注意:有的demo里面没有将new ConcreteBuilder();放在客户使用代码里面,直接在Director里面new出来使用,客户端只和导演者类交互。
说明:导演者角色是与客户端打交道的角色。导演者将客户端创建产品的请求划分为对各个零件的建造请求,再将这些请求委派给具体建造者角色。
具体建造者角色是做具体建造工作的,但是却不为客户端所知。
3、优点:
a.建造者模式的封装性很好。
在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
b.很容易进行扩展。
如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码
4、和工厂模式的区别:
解释1:
建造者模式仅仅只比工厂模式多了一个“导演类”的角色,建造者模式一般用来创建更为复杂的对象。
工厂模式:将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品
建造模式:建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。
由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
解释2:
工厂模式:一般都是创建一个产品,注重的是把这个产品创建出来就行,只要创建出来,不关心这个产品的组成部分。
从代码上看,工厂模式就是一个方法,用这个方法就能生产出产品。
建造模式:也是创建一个产品,但是不仅要把这个产品创建出来,还要关系这个产品的组成细节,组成过程。
从代码上看,建造者模式在建造产品时,这个产品有很多方法,建造者模式会根据这些相同方法但是不同执行顺序建造出不同组成细节的产品。
工厂模式关心整体,建造者模式关心细节。
5、实际的例子演示:
a.抽象类AutoMessage源代码,send()操作仅仅是示意性的,并没有给出任何发送电子邮件的代码。
public abstract 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;
}
}
b.具体产品类
具体产品类WelcomeMessage
public class WelcomeMessage extends AutoMessage {
/**
* 构造子
*/
public WelcomeMessage(){
System.out.println("发送欢迎信息");
}
}
具体产品类GoodbyeMessage
public class GoodbyeMessage extends AutoMessage{
/**
* 构造子
*/
public GoodbyeMessage(){
System.out.println("发送欢送信息");
}
}
c.抽象建造者类
public abstract class Builder {
protected AutoMessage msg;
//标题零件的建造方法
public abstract void buildSubject();
//内容零件的建造方法
public abstract void buildBody();
//收件人零件的建造方法
public void buildTo(String to){
msg.setTo(to);
}
//发件人零件的建造方法
public void buildFrom(String from){
msg.setFrom(from);
}
//发送时间零件的建造方法
public void buildSendDate(){
msg.setSendDate(new Date());
}
/**
* 邮件产品完成后,用此方法发送邮件
* 此方法相当于产品返还方法
*/
public void sendMessage(){
msg.send();
}
}
d.具体建造者
具体建造者WelcomeBuilder
public class WelcomeBuilder extends Builder {
public WelcomeBuilder(){
msg = new WelcomeMessage();
}
@Override
public void buildBody() {
// TODO Auto-generated method stub
msg.setBody("欢迎内容");
}
@Override
public void buildSubject() {
// TODO Auto-generated method stub
msg.setSubject("欢迎标题");
}
}
具体建造者GoodbyeBuilder
public class GoodbyeBuilder extends Builder {
public GoodbyeBuilder(){
msg = new GoodbyeMessage();
}
@Override
public void buildBody() {
// TODO Auto-generated method stub
msg.setBody("欢送内容");
}
@Override
public void buildSubject() {
// TODO Auto-generated method stub
msg.setSubject("欢送标题");
}
}
e.导演者Director
这个类提供一个construct()方法,此方法调用建造者的建造方法,包括buildTo()、buildFrom()、buildSubject()、buildBody()、buildSendDate()等,
从而一部分一部分地建造出产品对象,既AutoMessage对象。
public class Director {
Builder builder;
/**
* 构造子
*/
public Director(Builder builder){
this.builder = builder;
}
/**
* 产品构造方法,负责调用各零件的建造方法
*/
public void construct(String toAddress , String fromAddress){
this.builder.buildTo(toAddress);
this.builder.buildFrom(fromAddress);
this.builder.buildSubject();
this.builder.buildBody();
this.builder.buildSendDate();
this.builder.sendMessage();
}
}
f.客户端Client
public class Client {
public static void main(String[] args) {
Builder builder = new WelcomeBuilder();
Director director = new Director(builder);
//调用construct方法构造AutoMessage对象,发送邮件
director.construct("toAddress@126.com", "fromAddress@126.com");
}
}