下面了例子来自《Java 与模式》。
假设有一个是用 Java 建造的电子杂志系统,定期地向用户的电子邮件信箱发送电子杂志。用户可以通过网页订阅,也可以通过网页结束订阅。当客户开始订阅时,系统发送一封电子邮件表示欢迎,当客户结束订阅时,系统发送一封电子邮件表示欢送。本例子就是这个系统负责发送“欢迎”和“欢送”邮件的模块。
1. 类图
2. Java实现代码
package cn.edu.ynu.sei.builder;
import java.util.Date;
import java.util.Properties;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
/**
* 邮件消息
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public abstract class AutoMessage
{
protected String subject = "";
protected String body = "";
protected String from = "";
protected String to = "";
protected Date sendDate = null;
public AutoMessage(){}
public void send()
{
// 你的 SMTP 服务器地址
String smtpHost = "smtp.mycompany.com";
// 发送者的邮件地址
String from = "[email protected]";
// 收信者的邮件地址
String to = "[email protected]";
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
Session session = Session.getDefaultInstance(props, null);
try
{
InternetAddress[] address = {new InternetAddress(to)};
MimeMessage message;
// 创建 message 对象
message = new MimeMessage(session);
// 建造发件人位元址零件
message.setFrom(new InternetAddress(from));
// 建造主题零件
message.setSubject("Hello from Jeff");
// 建造发送时间零件
message.setSentDate(sendDate);
// 建造内容零件
message.setText("Hello, How are things going?");
// 发送邮件,相当于产品接收方法
Transport.send(message);
System.out.println("Email has been sent.");
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* @return the subject
*/
public String getSubject()
{
return subject;
}
/**
* @param subject the subject to set
*/
public void setSubject(String subject)
{
this.subject = subject;
}
/**
* @return the body
*/
public String getBody()
{
return body;
}
/**
* @param body the body to set
*/
public void setBody(String body)
{
this.body = body;
}
/**
* @return the from
*/
public String getFrom()
{
return from;
}
/**
* @param from the from to set
*/
public void setFrom(String from)
{
this.from = from;
}
/**
* @return the sendDate
*/
public Date getSendDate()
{
return sendDate;
}
/**
* @param sendDate the sendDate to set
*/
public void setSendDate(Date sendDate)
{
this.sendDate = sendDate;
}
/**
* @return the to
*/
public String getTo()
{
return to;
}
/**
* @param to the to to set
*/
public void setTo(String to)
{
this.to = to;
}
}
import java.util.Date;
import java.util.Properties;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
/**
* 邮件消息
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public abstract class AutoMessage
{
protected String subject = "";
protected String body = "";
protected String from = "";
protected String to = "";
protected Date sendDate = null;
public AutoMessage(){}
public void send()
{
// 你的 SMTP 服务器地址
String smtpHost = "smtp.mycompany.com";
// 发送者的邮件地址
String from = "[email protected]";
// 收信者的邮件地址
String to = "[email protected]";
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
Session session = Session.getDefaultInstance(props, null);
try
{
InternetAddress[] address = {new InternetAddress(to)};
MimeMessage message;
// 创建 message 对象
message = new MimeMessage(session);
// 建造发件人位元址零件
message.setFrom(new InternetAddress(from));
// 建造主题零件
message.setSubject("Hello from Jeff");
// 建造发送时间零件
message.setSentDate(sendDate);
// 建造内容零件
message.setText("Hello, How are things going?");
// 发送邮件,相当于产品接收方法
Transport.send(message);
System.out.println("Email has been sent.");
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* @return the subject
*/
public String getSubject()
{
return subject;
}
/**
* @param subject the subject to set
*/
public void setSubject(String subject)
{
this.subject = subject;
}
/**
* @return the body
*/
public String getBody()
{
return body;
}
/**
* @param body the body to set
*/
public void setBody(String body)
{
this.body = body;
}
/**
* @return the from
*/
public String getFrom()
{
return from;
}
/**
* @param from the from to set
*/
public void setFrom(String from)
{
this.from = from;
}
/**
* @return the sendDate
*/
public Date getSendDate()
{
return sendDate;
}
/**
* @param sendDate the sendDate to set
*/
public void setSendDate(Date sendDate)
{
this.sendDate = sendDate;
}
/**
* @return the to
*/
public String getTo()
{
return to;
}
/**
* @param to the to to set
*/
public void setTo(String to)
{
this.to = to;
}
}
package cn.edu.ynu.sei.builder;
import java.util.Date;
/**
* 抽象建造者
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public abstract class Builder
{
protected AutoMessage msg;
public Builder(){}
/**
* 主题零件建造方法
*/
public abstract void buildSubject();
/**
* 内容零件建造方法
*/
public abstract void buildBody();
/**
* 发送人零件建造方法
* @param from
*/
public void buildFrom(String from)
{
msg.setFrom(from);
}
/**
* 收件人零件建造方法
* @param to
*/
public void buildTo(String to)
{
System.out.println(to);
msg.setTo(to);
}
/**
* 发送时间零件建造方法
*/
public void buildSendDate()
{
msg.setSendDate(new Date());
}
/**
* 邮件产品完成后,用此方法发送邮件<br>
* 此方法相当于产品返回方法
*/
public void sendMessage()
{
msg.send();
}
}
import java.util.Date;
/**
* 抽象建造者
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public abstract class Builder
{
protected AutoMessage msg;
public Builder(){}
/**
* 主题零件建造方法
*/
public abstract void buildSubject();
/**
* 内容零件建造方法
*/
public abstract void buildBody();
/**
* 发送人零件建造方法
* @param from
*/
public void buildFrom(String from)
{
msg.setFrom(from);
}
/**
* 收件人零件建造方法
* @param to
*/
public void buildTo(String to)
{
System.out.println(to);
msg.setTo(to);
}
/**
* 发送时间零件建造方法
*/
public void buildSendDate()
{
msg.setSendDate(new Date());
}
/**
* 邮件产品完成后,用此方法发送邮件<br>
* 此方法相当于产品返回方法
*/
public void sendMessage()
{
msg.send();
}
}
package cn.edu.ynu.sei.builder;
/**
* 邮件发送系统客户
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class Client
{
private static Builder builder;
private static Director director;
public static void main(String[] args)
{
builder = new WelcomeBuilder();
director = new Director(builder);
director.construct("[email protected]", "[email protected]");
}
}
/**
* 邮件发送系统客户
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class Client
{
private static Builder builder;
private static Director director;
public static void main(String[] args)
{
builder = new WelcomeBuilder();
director = new Director(builder);
director.construct("[email protected]", "[email protected]");
}
}
package cn.edu.ynu.sei.builder;
/**
* 导演角色
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class Director
{
Builder builder;
public Director(Builder builder)
{
this.builder = builder;
}
/**
* 产品构建方法,负责调用各零件建造方法
* @param toAddress
* @param fromAddress
*/
public void construct(String toAddress, String fromAddress)
{
this.builder.buildSubject();
this.builder.buildBody();
this.builder.buildTo(toAddress);
this.builder.buildFrom(fromAddress);
this.builder.buildSendDate();
this.builder.sendMessage();
}
}
/**
* 导演角色
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class Director
{
Builder builder;
public Director(Builder builder)
{
this.builder = builder;
}
/**
* 产品构建方法,负责调用各零件建造方法
* @param toAddress
* @param fromAddress
*/
public void construct(String toAddress, String fromAddress)
{
this.builder.buildSubject();
this.builder.buildBody();
this.builder.buildTo(toAddress);
this.builder.buildFrom(fromAddress);
this.builder.buildSendDate();
this.builder.sendMessage();
}
}
package cn.edu.ynu.sei.builder;
public class GoodbyeBuilder extends Builder
{
private static final String subject = "Thank you for bing with us!";
public GoodbyeBuilder()
{
msg = new GoodbyeMessage();
}
/**
* 主题零件建造方法
*/
public void buildSubject()
{
msg.setSubject(subject);
}
/**
* 内容零件建造方法
*/
public void buildBody()
{
String body = "Oops! You have chosen to leave.";
msg.setBody(body);
}
}
public class GoodbyeBuilder extends Builder
{
private static final String subject = "Thank you for bing with us!";
public GoodbyeBuilder()
{
msg = new GoodbyeMessage();
}
/**
* 主题零件建造方法
*/
public void buildSubject()
{
msg.setSubject(subject);
}
/**
* 内容零件建造方法
*/
public void buildBody()
{
String body = "Oops! You have chosen to leave.";
msg.setBody(body);
}
}
package cn.edu.ynu.sei.builder;
/**
* 欢送消息,产品类
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class GoodbyeMessage extends AutoMessage
{
public GoodbyeMessage()
{
System.out.println("Entering Goodbye Message.");
}
/**
* 某个业务逻辑方法
*/
public void sayGoodbey()
{
System.out.println("Goodbye.");
}
}
/**
* 欢送消息,产品类
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class GoodbyeMessage extends AutoMessage
{
public GoodbyeMessage()
{
System.out.println("Entering Goodbye Message.");
}
/**
* 某个业务逻辑方法
*/
public void sayGoodbey()
{
System.out.println("Goodbye.");
}
}
package cn.edu.ynu.sei.builder;
/**
* 具体欢迎消息的建造者
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class WelcomeBuilder extends Builder
{
private static final String subject = "Welcome to phiharmony news group!";
public WelcomeBuilder()
{
msg = new WelcomeMessage();
}
/**
* 主题零件建造方法
*/
public void buildSubject()
{
msg.setSubject(subject);
}
/**
* 内容零件建造方法
*/
public void buildBody()
{
String body = "Congratulations for making the right choice!";
msg.setBody(body);
}
}
/**
* 具体欢迎消息的建造者
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class WelcomeBuilder extends Builder
{
private static final String subject = "Welcome to phiharmony news group!";
public WelcomeBuilder()
{
msg = new WelcomeMessage();
}
/**
* 主题零件建造方法
*/
public void buildSubject()
{
msg.setSubject(subject);
}
/**
* 内容零件建造方法
*/
public void buildBody()
{
String body = "Congratulations for making the right choice!";
msg.setBody(body);
}
}
package cn.edu.ynu.sei.builder;
/**
* 欢迎消息,产品类
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class WelcomeMessage extends AutoMessage
{
public WelcomeMessage()
{
System.out.println("Entring Welcome Message.");
}
/**
* 某个业务逻辑方法
*/
public void sayWelcome()
{
System.out.println("Welcome");
}
}
/**
* 欢迎消息,产品类
*
* @author 88250
* @version 1.0.0, 2007-8-24
*/
public class WelcomeMessage extends AutoMessage
{
public WelcomeMessage()
{
System.out.println("Entring Welcome Message.");
}
/**
* 某个业务逻辑方法
*/
public void sayWelcome()
{
System.out.println("Welcome");
}
}
3. 总结
看了以上内容,你可能已经注意到了,建造者模式于抽象工厂模式非常相像,两者都是用来创建同时属于几个产品族的对象的模式。在抽象工厂模式中,每一次工厂对象被调用时都会返回一个完整的产品对象,而客户端可能会决定把这个产品组装成一个更大更复杂的产品,也可能不会。而建造这模式则不同,它一点一点地建造出一个复杂的产品,而这个产品的组织过程就发生在建造者角色的内部,客户端拿到的是一个完整的最终产品。
所以,可以这样理解,抽象工厂处在更加具体的尺度上,而建造者则处于更加宏观的尺度上。一个系统可以由一个建造者和一个抽象工厂组成,客户端通过调用建造角色,间接地调用另一个抽象工厂的工厂角色。工厂模式返回不同产品族的零件,而建造者模式则把它们组织起来。