一。定义
将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示
builder模式是一步一步创建一个复杂对象,允许用户在不知道内部构建细节的情况下,更精细的控制对象的构建过程。
二。使用场景
相同的方法,不同的执行顺序,产生不同的时间结果时
多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时
产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用,这个时候使用构造者模式非常合适
当初始化一个对象特别复杂,如参数比较多,且很多参数都具有默认值时
三。builder模式的实现
**************************************************************************************
package com.yinazh.designpattern.builder;
public abstract class Computer{
protected String mBoard;
protected String mDisplay;
protected String mOS;
protected Computer(){}
public void setBoard(String board){
this.mBoard = board;
}
public void setDisplay(String display){
this.mDisplay = display;
}
public abstract void setOS();
public String toString(){
return "Computer{mBoard = " + mBoard + ", mDisplay = " + mDisplay + ", mOS = " + mOS;
}
}
public class MacBook extends Computer{
protected MacBook(){}
public void setOS(){
mOS = "Mac OS"
}
}
public abstract class Builder{
public abstract void buildBoard(String board);
public abstract void buildDisplay(String display);
public abstract void buildOS();
public abstract Computer create();
}
public class MacbookBuilder extends Builder{
private Computer mComputer = new MacBook();
public void buildBoard(String board){
mComputer.setBoard(board);
}
public void buildDisplay(String display){
mComputer.setDisplay(display);
}
public void buildOS(){
mComputer.setOS();
}
public Computer create(){
return mComputer;
}
}
public class Director{
Builder mBuilder = null;
public Director(Builder builder){
mBuilder = builder;
}
public void construct(String board, String display){
mBuilder.buildBoard(board);
mBuilder.buildDisplay(display);
mBUilder.buildOS();
}
}
public class Test{
pubilc static void main(String[] args){
Builder builder = new MacbookBuilder();
Director pcDirector = new Director(builder);
pcDirector.construct("aaaaaaa", "bbbbbb");
System.out.println("Computer Info = " + builder.create().toString());
}
}
**************************************************************************************
上述示例中,通过具体的MacbookBuidler来构建Macbook对象,而Director封装了构建复杂产品对象的过程,对外隐藏构建细节。Builder与Director一起将一个复杂对象的构建与它的表示分离,是的同样的狗年过程可以创建不同的对象。
值得注意的是,在现实的开发中,Director角色经常是省略的,而直接使用一个Builder来进行对象的组装,这个Builder通常为链式调用,它的关键点是每个setter方法都返回自身,也就是return this,这样就使得setter方法可以链式调用,具体示例如下:
**************************************************************************************
package com.yinazh.designpattern;
//实现成员Weapon
public enum Weapon {
DAGGER, SWORD, AXE, WARHAMMER, BOW;
@Override
public String toString() {
return name().toLowerCase();
}
}
//实现成员Armor
public enum Armor {
CLOTHES("clothes"), LEATHER("leather"), CHAIN_MAIL("chain mail"), PLATE_MAIL("plate mail");
private String title;
Armor(String title) {
this.title = title;
}
@Override
public String toString() {
return title;
}
}
public enum HairColor {
WHITE, BLOND, RED, BROWN, BLACK;
@Override
public String toString() {
return name().toLowerCase();
}
}
public enum HairType {
BALD("bald"), SHORT("short"), CURLY("curly"), LONG_STRAIGHT("long straight"), LONG_CURLY("long curly");
private String title;
HairType(String title) {
this.title = title;
}
@Override
public String toString() {
return title;
}
}
public enum Profession {
WARRIOR, THIEF, MAGE, PRIEST;
@Override
public String toString() {
return name().toLowerCase();
}
}
//实现复杂产品类,类中使用静态内部类实现简化builder模式,在构建产品的时候,可以链式构建
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HairColor hairColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
public Profession getProfession() {
return profession;
}
public String getName() {
return name;
}
public HairType getHairType() {
return hairType;
}
public HairColor getHairColor() {
return hairColor;
}
public Armor getArmor() {
return armor;
}
public Weapon getWeapon() {
return weapon;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("This is a ")
.append(profession)
.append(" named ")
.append(name);
if (hairColor != null || hairType != null) {
sb.append(" with ");
if (hairColor != null) {
sb.append(hairColor).append(' ');
}
if (hairType != null) {
sb.append(hairType).append(' ');
}
sb.append(hairType != HairType.BALD ? "hair" : "head");
}
if (armor != null) {
sb.append(" wearing ").append(armor);
}
if (weapon != null) {
sb.append(" and wielding a ").append(weapon);
}
sb.append('.');
return sb.toString();
}
/**
*
* The builder class.
*
*/
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
/**
* Constructor
*/
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder withHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder withHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder withArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder withWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
}
//测试
public class App {
public static void main(String[] args) {
Hero mage =new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK)
.withWeapon(Weapon.DAGGER).build();
Hero warrior =new Hero.Builder(Profession.WARRIOR, "Amberjill").withHairColor(HairColor.BLOND)
.withHairType(HairType.LONG_CURLY).withArmor(Armor.CHAIN_MAIL).withWeapon(Weapon.SWORD)
.build();
Hero thief =new Hero.Builder(Profession.THIEF, "Desmond").withHairType(HairType.BALD)
.withWeapon(Weapon.BOW).build();
}
}
**************************************************************************************
四。在android中的应用
常见的使用builder模式的,就是AlertDialog的创建。
五。优缺点
优点: 良好的封装性,使用建造者模式可以使客户端不必知道产品内部的组成细节
缺点:会产生多余的Builder对象以及Director对象,消耗内存。
将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示
builder模式是一步一步创建一个复杂对象,允许用户在不知道内部构建细节的情况下,更精细的控制对象的构建过程。
二。使用场景
相同的方法,不同的执行顺序,产生不同的时间结果时
多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时
产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用,这个时候使用构造者模式非常合适
当初始化一个对象特别复杂,如参数比较多,且很多参数都具有默认值时
三。builder模式的实现
**************************************************************************************
package com.yinazh.designpattern.builder;
public abstract class Computer{
protected String mBoard;
protected String mDisplay;
protected String mOS;
protected Computer(){}
public void setBoard(String board){
this.mBoard = board;
}
public void setDisplay(String display){
this.mDisplay = display;
}
public abstract void setOS();
public String toString(){
return "Computer{mBoard = " + mBoard + ", mDisplay = " + mDisplay + ", mOS = " + mOS;
}
}
public class MacBook extends Computer{
protected MacBook(){}
public void setOS(){
mOS = "Mac OS"
}
}
public abstract class Builder{
public abstract void buildBoard(String board);
public abstract void buildDisplay(String display);
public abstract void buildOS();
public abstract Computer create();
}
public class MacbookBuilder extends Builder{
private Computer mComputer = new MacBook();
public void buildBoard(String board){
mComputer.setBoard(board);
}
public void buildDisplay(String display){
mComputer.setDisplay(display);
}
public void buildOS(){
mComputer.setOS();
}
public Computer create(){
return mComputer;
}
}
public class Director{
Builder mBuilder = null;
public Director(Builder builder){
mBuilder = builder;
}
public void construct(String board, String display){
mBuilder.buildBoard(board);
mBuilder.buildDisplay(display);
mBUilder.buildOS();
}
}
public class Test{
pubilc static void main(String[] args){
Builder builder = new MacbookBuilder();
Director pcDirector = new Director(builder);
pcDirector.construct("aaaaaaa", "bbbbbb");
System.out.println("Computer Info = " + builder.create().toString());
}
}
**************************************************************************************
上述示例中,通过具体的MacbookBuidler来构建Macbook对象,而Director封装了构建复杂产品对象的过程,对外隐藏构建细节。Builder与Director一起将一个复杂对象的构建与它的表示分离,是的同样的狗年过程可以创建不同的对象。
值得注意的是,在现实的开发中,Director角色经常是省略的,而直接使用一个Builder来进行对象的组装,这个Builder通常为链式调用,它的关键点是每个setter方法都返回自身,也就是return this,这样就使得setter方法可以链式调用,具体示例如下:
**************************************************************************************
package com.yinazh.designpattern;
//实现成员Weapon
public enum Weapon {
DAGGER, SWORD, AXE, WARHAMMER, BOW;
@Override
public String toString() {
return name().toLowerCase();
}
}
//实现成员Armor
public enum Armor {
CLOTHES("clothes"), LEATHER("leather"), CHAIN_MAIL("chain mail"), PLATE_MAIL("plate mail");
private String title;
Armor(String title) {
this.title = title;
}
@Override
public String toString() {
return title;
}
}
public enum HairColor {
WHITE, BLOND, RED, BROWN, BLACK;
@Override
public String toString() {
return name().toLowerCase();
}
}
public enum HairType {
BALD("bald"), SHORT("short"), CURLY("curly"), LONG_STRAIGHT("long straight"), LONG_CURLY("long curly");
private String title;
HairType(String title) {
this.title = title;
}
@Override
public String toString() {
return title;
}
}
public enum Profession {
WARRIOR, THIEF, MAGE, PRIEST;
@Override
public String toString() {
return name().toLowerCase();
}
}
//实现复杂产品类,类中使用静态内部类实现简化builder模式,在构建产品的时候,可以链式构建
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HairColor hairColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
public Profession getProfession() {
return profession;
}
public String getName() {
return name;
}
public HairType getHairType() {
return hairType;
}
public HairColor getHairColor() {
return hairColor;
}
public Armor getArmor() {
return armor;
}
public Weapon getWeapon() {
return weapon;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("This is a ")
.append(profession)
.append(" named ")
.append(name);
if (hairColor != null || hairType != null) {
sb.append(" with ");
if (hairColor != null) {
sb.append(hairColor).append(' ');
}
if (hairType != null) {
sb.append(hairType).append(' ');
}
sb.append(hairType != HairType.BALD ? "hair" : "head");
}
if (armor != null) {
sb.append(" wearing ").append(armor);
}
if (weapon != null) {
sb.append(" and wielding a ").append(weapon);
}
sb.append('.');
return sb.toString();
}
/**
*
* The builder class.
*
*/
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
/**
* Constructor
*/
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder withHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder withHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder withArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder withWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
}
//测试
public class App {
public static void main(String[] args) {
Hero mage =new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK)
.withWeapon(Weapon.DAGGER).build();
Hero warrior =new Hero.Builder(Profession.WARRIOR, "Amberjill").withHairColor(HairColor.BLOND)
.withHairType(HairType.LONG_CURLY).withArmor(Armor.CHAIN_MAIL).withWeapon(Weapon.SWORD)
.build();
Hero thief =new Hero.Builder(Profession.THIEF, "Desmond").withHairType(HairType.BALD)
.withWeapon(Weapon.BOW).build();
}
}
**************************************************************************************
四。在android中的应用
常见的使用builder模式的,就是AlertDialog的创建。
五。优缺点
优点: 良好的封装性,使用建造者模式可以使客户端不必知道产品内部的组成细节
缺点:会产生多余的Builder对象以及Director对象,消耗内存。