Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

【设计模式】Builder模式

$
0
0

定义

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

将复杂对象的创建过程与该对象的表示分离开来,以便让同一个创建过程可以创建出不同的表示。

类图



 

角色

  1. Builder:
    定义一个抽象接口,用于创建Product组成部分
  2. ConcreteBuilder:
    构建并组装Product组成部分;
    定义并跟踪所创建的表示(Product?);
    提供接口,用于查询product。
  3. Director:
    使用Builder接口构建对象
  4. Product:
    表示所创建的复杂对象;——ConcreteBuilder构建product的内部表示并定义它的组装过程;
    包含定义组成部分的类。

 

示例代码

  • Product

public class MyFile {
  private FileHead fhead;
  private FileContent fcontent;
  private FileEnd fend;
   
  public FileContent getFcontent() {
    return fcontent;
  }
  public void setFcontent(FileContent fcontent) {
    this.fcontent = fcontent;
  }
  public FileEnd getFend() {
    return fend;
  }
  public void setFend(FileEnd fend) {
    this.fend = fend;
  }
  public FileHead getFhead() {
    return fhead;
  }
  public void setFhead(FileHead fhead) {
    this.fhead = fhead;
  }
  public void write(String path) throws IOException{
    File f=new File(path);
    FileWriter fw=new FileWriter(f);
    PrintWriter out=new PrintWriter(fw);
    out.println(fhead.getValue());
    out.println(fcontent.getValue());
    out.println(fend.getValue());
    out.close();   
  }
}
 
Product Part
 
public class FileHead {
  private String value;
  public String getValue() {
    return value;
  }
  public void setValue(String value) {
    this.value = value;
  }
}
 
public class FileContent{
  private String value;
  ...
}
 
public class FileEnd {
  private String value;
  ...
}
  • Builder

public interface FileBuilder {
  void buildHead();
  void buildContent();
  void buildEnd();
  MyFile getResult();
}
  • ConcreteBuilder

public class TxtBuilder implements FileBuilder{
  private FileHead fh=new FileHead();
  private FileContent fc=new FileContent();;
  private FileEnd fe=new FileEnd();
  public void buildHead() {
    fh.setValue("This is text file");
  }
  public void buildContent() {
    fc.setValue("this is my content");
  }
  public void buildEnd() {
    fe.setValue("this is the end of the file");
  }
  public MyFile getResult() {
    MyFile my=new MyFile();
    my.setFcontent(fc);
    my.setFhead(fh);
    my.setFend(fe);
    return my;
  }
}
 
 
public class XmlBuilder implements FileBuilder {
      private FileHead fh=new FileHead();
      private FileContent fc=new FileContent();
      private FileEnd fe=new FileEnd();
     
  public void buildHead() {
    fh.setValue("<?xml version=\"1.0\" encoding=\"GB2312\"?><content>"); 
  }
  public void buildContent() {
    fc.setValue("<test>asdasd</test>");
  }
  public void buildEnd() {
    fe.setValue("</content>");   
  }
  //组装product
  public MyFile getResult() {
    MyFile my=new MyFile();
    my.setFcontent(fc);
    my.setFhead(fh);
    my.setFend(fe);
    return my;
  }
}
  • Director


public class FileDirector {
      private FileBuilder filebuilder;
      public FileDirector(FileBuilder filebuilder){
        this.filebuilder=filebuilder;
      }
 
      //一步一步创建product
      public void construct(){
        filebuilder.buildHead();
        filebuilder.buildContent();
        filebuilder.buildEnd();
      }
}
  • Client

public class Demo {
  public static void main(String[] args) throws IOException {
              //TxtBuilder
              FileBuilder fb=new TxtBuilder();
              FileDirector fd=new FileDirector(fb);             
              fd.construct();
              MyFile my = fb.getResult();
              my.write("D:/test.txt");
             
              //XmlBuilder --改变builder,就改变了product的内部表示
              FileBuilder fbxml=new XmlBuilder();
              FileDirector fdxml=new FileDirector(fbxml);
              fdxml.construct();
              MyFile myxml=fbxml.getResult();
              myxml.write("D:/test1.xml");
  }
}

 

优点

  1. 允许改变product的内部表示,定义一个新的builder即可。因为builder隐藏了product的表示和内部结构,也隐藏了product是如何组装的。
  2. 将构建和表示的代码分离开。将复杂对象的创建和表示封装起来,提供了模块化特性。每个ConcreteBuilder都定义了完整的创建和组装product的方法,不同的Director可以重用这些方法来构造不同的product。——也就是说可以替换Director,以便生成不同的product。
  3. 能更好地控制构建过程。并非一蹴而就地构建出product,而是在director的控制下一步一步地构建product。

缺点

 

适用场景

  1. 复杂对象的创建逻辑、其组成部分的创建逻辑、组装逻辑,互相独立。
  2. 构建过程允许对象有不同的表示。

诀窍

  • AbstractBuilder中的方法留空,而不定义成抽象方法。
这样ConcreteBuilder就能按需实现方法,而不是实现所有方法。
  • 为什么没有AbstractProduct?

一般ConcreteBuilder构建的product表示的差异很大。客户端会给director配置某个具体的ConcreteBuilder,所以客户端也就知道了会创建那种product。

  • 为何不把builder中的逻辑移到Product中:
让Product尽可能小,易于理解和修改;
逻辑分开后,可以定义多种builder,实现不同的逻辑

 

Related Patterns

  • Abstract Factory也是用来创建复杂对象,但是它着重于创建产品族;Builder则着重于一步一步地创建复杂对象。Builder是在最后一步返回product;而Abstract Factory立即返回product。
  • Builder通常用来构建Composite

 

作者:vking_wang 发表于2013-11-17 16:26:08 原文链接
阅读:46 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>