建造(Builder)模式 【创建模式第六篇】

建造(Builder)模式
建造模式是对象的创建模式。
产品的内部表象:一个产品常有不同的组成成分作为产品的零件,这些零件有可能是对象,也有可能不是对象它们通常叫做产品的内部表象

角色:
1、抽象建造者角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,有多少个零件就有多少个建造方法

2、具体建造者角色:担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序的调用下创建产品的实例。
这个角色完成的人物包括:
1)实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作。
2)在建造过程完成后,提供产品的实例

3、导演者角色:担任这个角色的类调用具体建造者角色以创建产品对象。导演者角色并没有产品类的具体知识,真正拥有产品类
具体知识的是具体建造者角色。

4、产品角色:产品便是建造中的复杂对象。一般来说,一个系统会有多余一个的产品类,而且这些产品类并不一定有共同的接口
而完全可以是不想关联的。
(导演者角色是与客户端打交道的角色)
一般类说:没有一个产品类,就有一个相应的具体建造者类。

public class Driector{
private Builder builder;

//产品构造方法,负责调用各个零件建造方法
public void construct(){
builder = new ConcreteBuilder();
builder.buildPart1();
builder.buildPart2();
builder.retrieveResult(); //retrieve检索
}
}

//抽象建造者
public abstract class Builder{
//产品零件建造方法
public abstract void buildPart1();

public abstract void buildPart2();

//产品返回方法
public abstract Product retrieveResult();
}

//具体建造者
public class ConcreteBuilder extends Builder{
private Product product = new Product();

//产品返回方法
public Product retrieveResult(){
return product;
}

//产品零件建造方法
public void buildPart1(){
//build the first part of the product
}

public void buildPart2(){
//build the second part of the product
}
}

//产品类
public class Product{
//...................
}
//如果省略了导演者角色
//客户端代码
public class Client{
private static Builder builder;

public static void main(String args[]){
//创建建造者对象
builder = new Builder();

//拥有建造者对象的产品构造方法
builder.construct();

//调用建造者对象的产品返还方法以取得产品
Product product = builder.retrieveResult();
}
}

模板方法模式:
准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法迫使子类实现剩余的逻辑。不同的子类可以
以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式

如果系统的要求发生变化,要求有不同的零件生成逻辑时,那么设计师有两种选择:
1、一是修改这个退化的建造模式,将它改回成为完全的建造模式,这当然就要涉及到代码的修改了;
2、二是不修改代码,而是将Builder类扩展到不同的子类,在这些子类里面置换掉需要改变的建造方法

如果一个产品对象有着固定的几个零件,而且永远只有这几个零件。此时将产品类于建造类合并

*在很多情况下,建造模式实际上是将一个对象的性质建造过程外部化到独立的建造者对象中,并通过一个导演者角色对这些外部化的性质赋值
过程进行协调。

一个简单的发送电子邮件的客户端
import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class MailSender{
private static MineMessage message;

public static void main(String args[]){
//你的SMTP服务器地址
String smtpHost = "smtp.mycompany.com";
//发送者的地址
String from = "joff.yan@mycompany.com";
//收信者地址
String to = "ni.hao@youcompany.com";

Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);

Session session = Session.getDefaultInstance(props,null);

try{
InternetAddress[] address = new InternetAddress(to);
//创建Message对象
message = new MineMessage(session);
//建造发件人位元址零件
message.setFrom(new InternetAddress(from));
//建造收件人位元址零件
message.setRecipients(Message.RecipientType.TO,address);
//建造主题零件
messgae.setSubject("Hello from Jeff");
//建造发送时间零件
message.setSentDate(new Date());
//建造内部零件
message.setText("Hello,\nHow are things going?");

//发送邮件,相当于产品返回方法
Transport.send(message);
System.out.println("email has been sent.");
}catch(Exception e){
System.out.println(e);
}
}
}
///
//导演类
public class Director{
Builder builder;

public Director(Builder builder){
this.builder = builder;
}

//产品构造方法,负责调用各零件建造方法
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();
}
}

//抽象建造者类
import java.util.Date;

public abstract class Builder{
protected AutoMessage msg;

public Builder(){}

//主题零件的建造方法
public abstract void buildSubject();
//内容零件的建造方法
public abstract void buildBody();
//发件人零件的建造方法
public void buildFrom(String from){
msg.setFrom(from);
}
//收件人零件的建造方法
public void buildTo(String to){
System.out.println(to);
msg.setTo(to);
}
//发送时间零件的建造方法
public void buildSendDate(){
msg.setSendDate(new Date());
}
//邮件产品完成后,用此方法发送邮件
//此方法相当于产品返回方法
public void sendMessage(){
msg.send();
}
}

//具体建造类
public class WelcomeBuilder extends Builder{
private static final String subject = "Welcome to philharmony news group";

public WelcomeBuilder(){
msg = new WelcomeMessage();
}

//主题零件的建造方法
public void buildSubject(){
msg.setSubject(subject);
}

public void buildBody(){
String body = "Congratulations for making the choice!";
msg.setBody(body);
}

//邮件产品建造完成后,发送邮件
//此方法相当于产品返还方法
public void sendMessage(){
msg.send();
}
}

//在以下情况下应当使用建造模式
1) 需要生成的产品对象有复杂的内部结构。每一个内部成分本身可以是对象,也可以仅仅是一个对象(即产品对象)的一个组成成分
2) 需要生成的产品对象的属性相互依赖。301P
3) 在对象创建过程中会使用到系统中的其他一些对象,这些对象在产品对象的创建过程中不易得到


使用建造模式的效果:
1、建造模式的使用使得产品的内部表象可以独立地变化。使用建造模式可以使客户端不必知道产品内部组成的细节

2、每一个Builder都相对独立,而与其他的Builder无关

3、模式所建造的最终产品更易于控制。


建造模式与其他模式的关系
建造模式与抽象工厂模式的区别
1、在抽象工厂模式中,每一次工厂对象被调用时都会返回一个完整的产品对象,而客户端有可能会决定把这些
产品组成一个更大个复杂的产品,也有可能不会。建造类则不同,它一点一点地建造出一个复杂的产品,而这个产品
的组装过程就发生在建造者角色内部。建造者模式的客户端拿到的是一个完整的最后的产品
2、换言之,虽然抽象工厂模式与建造模式都是设计模式,但是抽象工厂模式处在更加具体的尺度上,
而建造模式则处于更加宏观的尺度上。一个系统可以由一个建造模式和一个抽象工厂模式的工厂角色。
工厂模式返回不同产品族的零件,而建造者模式则把它们组装起来。

建造模式与策略模式的区别
1、建造模式在结构上很接近于策略模式,事实上建造模式是策略模式的一种特殊情况,这两种模式的区别在于它们的用意
不同。建造模式适用于为客户端一点一点地建造新的对象,而不同类型的具体建造者角色虽然都拥有相同的接口,但是
它们所创建出来的对象则可能完全不同。策略模式的目的是为算法提供抽象的接口。换言之,一个具体策略类把一个算
法包装到一个对象里面,而不同的具体策略对象为一种一般性的服务提供不同的实现。

建造模式与合成模式的关系
1、产品的对象可以是对象,也可以不是对象,而是对象的某种组成成分。当产品的零件确实是对象时,产品对象就变成了
复合对象,因为产品内部还含有子对象。这种对象内含有子对象的结构,可以使用合成模式描述。

2、换言之,合成模式描述了一个对象树的组成结构,而建造模式则可以用来描述对象树的生成过程。

“一二三四五六七八九十”这是古代女子写给心上人的情诗,起含义:
“一别之后,两地相思,三月桃花随水转,四月琵琶未黄,奴我欲对镜心却乱。”
“五月石榴红似火,偏遇冷雨浇花端。六月伏天人热摇扇独我心寒。七弦琴无心弹”
“八行书无处传,九连环从中断,十里长庭望眼欲穿。”
这是一个数着月份逐步完成几个月相思的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值