菜鳥成長系列-Builder 建造者模式

菜鳥成長系列-概述
菜鳥成長系列-面向對象的四大基礎特性
菜鳥成長系列-多態、接口和抽象類
菜鳥成長系列-面向對象的6種設計原則
菜鳥成長系列-單例模式 菜鳥成長系列-工廠模式java

建造者模式也是建立型中的一種,用於負責建立對象。建造者模式能夠將一個產品的內部表象與產品的生成過程分割開來,從而可使一個建造過程生成具備不一樣的內部表象的產品對象。bash

什麼是產品的內部表象?

一個產品常有不用的組成成分做爲產品的零件,這些零件有多是對象,也有可能不是對象,他們一般又叫作產品的內部表象。不一樣的產品能夠有不一樣的內部表象,也就是能夠有不一樣的零件。使用建造者模式可使客戶端不須要知道所生成的產品對象有哪些零件,每一個產品的對應零件彼此有何不一樣,是怎麼建造出來的,以及怎樣組成產品。session

工廠模式與建造者模式

上一篇咱們討論了工廠模式,咱們知道工廠模式通常都是建立一個產品,注重的是把這個產品建立出來就行,只要建立出來,不關心這個產品的組成部分。從代碼上看,工廠模式就是一個方法,用這個方法就能生產出產品。那麼對於建造者模式呢? 建造者模式也是建立一個產品,可是不只要把這個產品建立出來,還要關係這個產品的組成細節, 組成過程。從代碼上看(下面給出),建造者模式在建造產品時,這個產品有不少方法,建造者模式會根據這些相同方法可是不一樣執行順序建造出不一樣組成細節的產品。app

建造者模式的結構

結構組件角色說明:

  • 抽象建造者(Builder):抽象類, 規範產品的組建,通常是由子類實現具體的組件過程
  • 具體建造者(ConcreteBuilder ):具體的構建器
  • 導演者(Director) : 統一組裝過程(可省略)
  • 產品(Product):產品的抽象類

Director角色是與客戶端打交道的角色。Director將客戶端建立產品的請求劃分爲對各個零件的建造請求,再將這些請求委派給具體的ConcreteBuilder角色。ConcreteBuilder是作具體建造工做的,可是對客戶端是透明的。ide

通常來講,每有一個產品類,就有一個相應的具體建造者類。這些產品應當有同樣數目的零件,而每有一個零件就相應的在全部的建造者角色裏有一個建造方法。post

建造一封郵件

經過代碼來看下各個角色的職責:ui

  • Director
package com.glmapper.model.builder;
/**
 * 
 * 導演者類
 * @author glmapper
 * @time 2017年12月30日上午11:33:26	
 * @version glmapper_v1.0
 *
 */
public class Director {
	private Builder builder;
	/**
	 * 產品構造方法,負責調用各個零件建造方法
	 */
	public EmailProduct construct(){
		builder = new ConcreteBuilder();
		builder.buildFromAddress();
		builder.buildToAddress();
		builder.buildSubject();
		builder.buildContent();
		builder.buildSupplement();
		return builder.returnEmailProduct();
	}
}
複製代碼
  • Builder
package com.glmapper.model.builder;
/**
 * 抽象建造者 提供不一樣的構建組件方法
 * @author glmapper
 * @time 2017年12月30日上午11:31:34	
 * @version glmapper_v1.0
 *
 */
public interface Builder {
	/**
	 * 構建發件人信息
	 */
	public void buildFromAddress();
	/**
	 * 構建收件人信息
	 */
	public void buildToAddress();
	/**
	 * 構建郵件內容
	 */
	public void buildContent();
	/**
	 * 構建郵件附件
	 */
	public void buildSupplement();
	/**
	 * 構建郵件主題
	 */
	public void buildSubject();
	/**
	 * 返回構建的產品
	 */
	public EmailProduct returnEmailProduct();
	
}
複製代碼
  • ConcreteBuilder
package com.glmapper.model.builder;
/**
 * 
 * 具體產品的建造器
 * @author glmapper
 * @time 2017年12月30日上午11:31:11	
 * @version glmapper_v1.0
 *
 */
public class ConcreteBuilder implements Builder{
	
	private EmailProduct emailProduct = new EmailProduct();
	public void buildFromAddress() {
		emailProduct.setFromAddress("00001111@glmapper.com");
	}

	public void buildToAddress() {
		emailProduct.setToAddress("00001112@glmapper.com");
	}

	public void buildContent() {
		emailProduct.setContent("我寫了一個建造者模式的例子,但願大佬給點意見");
	}

	public void buildSupplement() {
		emailProduct.setSupplement("附件:BuilderDemo.rar");
	}

	public void buildSubject() {
		emailProduct.setSubject("給大佬的一封建造者模式的Demo");
	}

	public EmailProduct returnEmailProduct() {
		System.out.println(emailProduct.toString());
		return emailProduct;
	}

}

複製代碼
  • Product
package com.glmapper.model.builder;
/**
 * 產品類(產品類中包括不一樣組件:此處使用字段方式模式組件)
 * @author glmapper
 * @time 2017年12月30日上午11:30:13	
 * @version glmapper_v1.0
 *
 */
public class EmailProduct {
	/**
	 * 發件地址
	 */
	private String fromAddress;
	/**
	 * 收件地址
	 */
	private String toAddress;
	/**
	 * 郵件主題
	 */
	private String subject;
	/**
	 * 郵件內容
	 */
	private String content;
	/**
	 * 郵件附件
	 */
	private String supplement;
	
	public String getFromAddress() {
		return fromAddress;
	}
	public void setFromAddress(String fromAddress) {
		this.fromAddress = fromAddress;
	}
	public String getToAddress() {
		return toAddress;
	}
	public void setToAddress(String toAddress) {
		this.toAddress = toAddress;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getSupplement() {
		return supplement;
	}
	public void setSupplement(String supplement) {
		this.supplement = supplement;
	}
	
	@Override
	public String toString() {
		return "EmailProduct [fromAddress=" + fromAddress + ", toAddress=" + toAddress + ", subject=" + subject
				+ ", content=" + content + ", supplement=" + supplement + "]";
	}
}

複製代碼
  • 客戶端
package com.glmapper.model.builder;
/**
 * 客戶端
 * @author glmapper
 * @time 2017年12月30日上午11:45:53	
 * @version glmapper_v1.0
 *
 */
public class MainTest {
	public static void main(String[] args) {
		new Director().construct();
	}
}
複製代碼
  • 結果
建造發件人信息組件...
建造收件人信息組件...
建造郵件主題信息組件...
建造郵件內容信息組件...
建造郵件附件信息組件...
(爲了方便看,這裏把結果的顯示作了調整)
EmailProduct :
[
    fromAddress=00001111@glmapper.com,
    toAddress=00001112@glmapper.com,
    subject=給大佬的一封建造者模式的Demo,
    content=我寫了一個建造者模式的例子,但願大佬給點意見,
    supplement=附件:BuilderDemo.rar
]
複製代碼

建造者模式的關注點

有些狀況下,一個對象會有一些重要的性質,在他們沒有恰當的值以前,對象不能做爲一個完整的產品來使用。就如上面發送一個電子郵件所示,電子郵件有發件人地址、收件人地址、主題、內容、附錄等部分,而在收件人地址沒有賦值以前,這個電子郵件是不能發送的。在某些狀況下,一個對象的一些性質必須按照某個順序賦值纔有意義,在某個性質沒有賦值以前,另外一個性質則沒法賦值。這些狀況使得性質自己的建造涉及到複雜的業務邏輯。this

而此時,對象至關於一個有待建造的產品,而對象的這些性質至關於產品的零件,建造產品的過程是建造零件的過程。因爲建造零件的過程很複雜,所以,這些零件的健在過程每每會被「外部化」到另外一個稱做爲建造者的對象裏,建造者對象返回給客戶端的是一個所有零件都建造完畢的產品對象。spa

在實際的應用過程當中,建造者模式也有不一樣的變種,好比說省略抽象建造者角色或者省略導演者角色等等,在某些狀況下,建造者模式能夠經過省略某些角色來達到過分到模板方法模式。設計

OK,關於建造者模式的其餘變種這裏就不討論了,留一個想象空間!(這段字表明一個微笑的表情(* ̄︶ ̄))

java中建造者模式:JavaMail

JavaMail是一組J2SE的擴展API的一個類庫,咱們可使用這個API來開發一個功能完備的電子郵件客戶端軟件。在JavaMail中就主要使用了建造者模式,固然還有咱們上一篇中說道的抽象工廠模式。

建造者模式在JavaMail中的使用

package com.glmapper.model.builder;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
/**
 * 郵件發送-建造者模式
 * @author glmapper
 * @time 2017年12月30日下午2:04:46	
 * @version glmapper_v1.0
 *
 */
public class MailSender {
	private static MimeMessage message;
	public static void main(String[] args) {
		//基本屬性
		String smptHost = "smpt.xxx.com";
		String fromAddress = "00001111@glmapper.com";
		String toAddress = "00001112@glmapper.com";
		Properties p= new Properties();
		p.put("mail.smtp.host", smptHost);
		Session session = Session.getDefaultInstance(p);
		try {
			InternetAddress to = new InternetAddress(toAddress);
			InternetAddress from = new InternetAddress(fromAddress);
			//建立message對象
			message = new MimeMessage(session);
			//下面就是組裝零件的過程
			message.setFrom(from);
			message.setRecipient(Message.RecipientType.TO, to);
			message.setSubject("hello builder");
			message.setText("我寫了一個建造者模式的例子,但願大佬給點意見");
			
			Transport.send(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

複製代碼

OK,建造者模式就到這裏了,你們元旦快樂!

相關文章
相關標籤/搜索