D 的个人博客

全职做开源,自由职业者

  menu

建造者(BUilder)模式的Java实现[00原创]

下面了例子来自《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 = "jeff.yan@mycompany.com";
    
    
// 收信者的邮件地址
    String to = "ni.hao@yourcompany.com";
    
    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();
    }
}

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(
"jeffyan77@yahoo.com""javapatterns@yahoo.com");
    }
}

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();
    }
}


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);
    }
}

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.");
    }
}

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);
    }
}

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");
    }
}

3. 总结

看了以上内容,你可能已经注意到了,建造者模式于抽象工厂模式非常相像,两者都是用来创建同时属于几个产品族的对象的模式。
在抽象工厂模式中,每一次工厂对象被调用时都会返回一个完整的产品对象,而客户端可能会决定把这个产品组装成一个更大更复杂的产品,也可能不会。而建造这模式则不同,它一点一点地建造出一个复杂的产品,而这个产品的组织过程就发生在建造者角色的内部,客户端拿到的是一个完整的最终产品。
所以,可以这样理解,抽象工厂处在更加具体的尺度上,而建造者则处于更加宏观的尺度上。一个系统可以由一个建造者和一个抽象工厂组成,客户端通过调用建造角色,间接地调用另一个抽象工厂的工厂角色。工厂模式返回不同产品族的零件,而建造者模式则把它们组织起来。

4. 参考文献

  《Design Patterns》、《Java与模式》