builder设计模式的使用以及优缺点

时间:2022-11-22 21:11:44

嗯,大家是否在开发过程中,经常遇到一个类拥有许多的属性呢。为了使这个类的使用便捷,我们通常情况下会给这个类多个构造器以及一个默认的无参数构造器。

但是当参数的个数达到四个或者更多的时候,你是否会经常忘记这几个参数之间的次序了呢。下面给出一个列子:

class A{

    private String a;

    private String b;

    private String c;

    private String d;

    private String e;   

    private String f;

    public A(){}

    public A(String a){

    // initialization in here

    }

 

    public A(String a, String b){}

    public A(String a, String b, String c){}

    public A(String a, String b, String c, String d){}   

    public A(String a, String b, String c, String d){}

    public A(String a, String b, String c, String d, String e){}

    public A(String a, String b, String c, String d, String e, String f){}  

}   

 

对于这样的一个类,拥有那么多的属性,并且构造器有多个,该如何初始化呢?如果用初始化:new A("a", "b", "c", "d", "e", "f");   你还记得住这些参数之间的次序吗??

你确保没有使用错误码???

所以为了解决这个问题,我们可以给类的每个属性都添加一个队形的setXxx()的方法,在使用的过程中,如下:

A a = new A();

a.setA("a");

a.setB("b");

...

使用起来就更加清晰和明了了。但是这样方式,使得该类的其他属性在被创建之后被修改,给程序带来了一些不安全性。所以为了解决这个矛盾,可以使用builder(构建器)设计模式了,下面给出一个具体点的列子:

package net.itaem.test;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * how to use the builder design pattern
 * @author luohong
 * */
public class ExcelTool {

 // the property be given and can't change again, so this class instance is safe when creating

 private final String sheetname;
 private final boolean is2007;
 private final List<String> headerList;
 private final List<ArrayList<Object>> contentList;
 private final String dateFormat;
 private final OutputStream outStream;
 
 public String toString(){
  return "sheetname:" + sheetname + ", is2007:" + ",headerList:"
         + headerList + ", dateFormat:" + dateFormat + ", contentList:"
         + contentList + ", outStream" + outStream + ", is2007:" + is2007;
 }
 
 public static class ExcelToolBuilder{
  public String sheetname;
  public boolean is2007;
  public List<String> headerList;
  public List<ArrayList<Object>> contentList;
  public String dateFormat;
  public OutputStream outStream;
  
  public ExcelToolBuilder(String sheetname, OutputStream outStream){
   this.sheetname = sheetname;
      this.outStream = outStream;
  }
  
  public ExcelToolBuilder is2007(boolean is2007){
   this.is2007 = is2007;
   return this;
  }
  
  public ExcelToolBuilder headerList(List<String> headerList){
   this.headerList = headerList;
      return this;
  }
  
  public ExcelToolBuilder contentList(List<ArrayList<Object>> contentList){
   this.contentList = contentList;
   return this;
  }
  
  public ExcelToolBuilder outStream(OutputStream outStream){
   this.outStream = outStream;
      return this;
  }
  
  public ExcelToolBuilder dateFormat(String dateFormat){
   this.dateFormat = dateFormat;
   return this;
  }
  
  public ExcelTool builder(){
   return new ExcelTool(this);
  }
  
 }
 
 private ExcelTool(ExcelToolBuilder etb){
  contentList = etb.contentList;
     headerList = etb.headerList;
  dateFormat = etb.dateFormat;
  outStream = etb.outStream;
  sheetname = etb.sheetname;
  is2007 = etb.is2007;
 }
 
 
 /**
  * test how to use this class to initialize
  * */
 public static void main(String[] args) throws FileNotFoundException {
  
  ExcelTool et = new ExcelTool.ExcelToolBuilder("example.xls",
    new FileOutputStream("c:\\example.xls"))
          .is2007(true).contentList(null).dateFormat("yyyy-MM-dd")
          .builder();
  //这是一种链式编程风格,使用起来更加清晰明了
  System.out.println(et);
 }
}

 

注意点:在使用builder的时候,让设置每个属性之后返回他自己本身,这样子可以采用链接的变成风格,使用起来更加方便快捷,具体部分可以参考红色字体部分.

缺点:当然,你也看到了,在使用构建器的时候,必须利用另外一个类来实例化另外一个类,这样子会使创建的时候创建更多的对象。这样子会损耗一定的性能...不过带来的好处是非常明显的。因为使用builder模式,每次设置属性的时候,都是具名的方法操作,是开发人员更容易使用,并且不需要给宿主类增加相应的setXxx方法,这样子,这个宿主类在创建之后是不可以修改的,在一些安全模式比较高的程序中,这点也是很重要的