博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA设计模式之建造者模式
阅读量:6086 次
发布时间:2019-06-20

本文共 6970 字,大约阅读时间需要 23 分钟。

一、定义

       建造者模式(Builder) : 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  

       建造者模式结构图,如下图1-1所示:

图 1-1 

二、实例展示

   Product类:产品类,由多个部件组成。

1 public class Product{
2 List
parts = new ArrayList
();3 public void Add(String part){4 parts.Add(part);5 } 6 public void Show(){
7 System.out.println("产品创建----"); 8 for(String part : parts){
9 System.out.println(part); 10 } 11 }12}

   Builder类:抽象建造者类,确定产品由两个部件PartA和PartB组成,并声明一个得到产品建造后结果的方法GetResult。

1  public abstract class Builder{2     public abstract void BuildPartA(); 3     public abstract void BuildPartB(); 4     public abstract Product GetResult();5  }

 

   ConcreteBuilder1:具体建造者类。

1 public class ConcreteBuilder1 extends Builder{
2 private Product product = new Product(); 3 @override4 public void BuildPartA(){5 product.Add("部件A");6 } 7 @Override 8 public void BuildPartB(){
9 product.Add("部件B"); 10 } 11 @override 12 public void Product GetResult(){
13 result product; 14 }15}

          ConcreteBuilder2:具体建造者类。

1 public class ConcreteBuilder2 extends Builder{
2 private Product product = new Product(); 3 @override4 public void BuildPartA(){5 product.Add("部件X");6 } 7 @override 8 public void BuildPartB(){
9 product.Add("部件Y"); 10 } 11 @override 12 public Product GetResult(){
13 return product; 14 }15}

          Director类:指挥者类。

1 public class Director{2     public void Construct(Builder builder){3         builder.BuildPartA(); 4         builder.BuildPartB();5     }6 }

         客户端代码,客户不知道具体的建造过程。

1 public static void Main(String[] args) {2     Director director = new Director(); 3     Builder  b1 = new ConcreteBuilder1(); 4     Builder  b2 = new ConcreteBuilder2(); 5     director.Construct(b1); 6     Product p1 = b1.GetResult(); 7     p1.Show(); 8     director.Construct(b2); 9     Product p2 = b2.GetResult(); 10    p2.Show(); 11}

 

三、使用场景

      1、需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。

      2、需要生成的产品对象的属性相互依赖,需要指定其生成顺序。

      3、对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。   

      4、隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

四、使用总结

      1、建造者模式优点: 

           1)  在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。

           2)每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。由于指挥者类针对抽象建造者编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便,符合 "开闭原则"。

           3)可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

 

      2、建造者模式缺点:

           1)  建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制。

           2)如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。

 

五、典型应用

       1java.lang.StringBuilder 中的建造者模式

            StringBuilder 的继承实现关系如下图 5-1 所示

       

图 5-1 

            Appendable 接口如下:

1  public interface Appendable {
2    Appendable append(CharSequence csq) throws IOException; 3    Appendable append(CharSequence csq, int start, int end) throws IOException; 4    Appendable append(char c) throws IOException; 5 }

          StringBuilder 中的 append 方法使用了建造者模式,不过装配方法只有一个,并不算复杂,append 方法返回的是 StringBuilder 自身 

1   public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
2    @Override 3    public StringBuilder append(String str) {
4        super.append(str); 5        return this; 6    } 7    // ...省略... 8 }

          StringBuilder 的父类 AbstractStringBuilder 实现了 Appendable 接口

1   abstract class AbstractStringBuilder implements Appendable, CharSequence {
2    char[] value; 3    int count; 4    public AbstractStringBuilder append(String str) {
5        if (str == null) 6            return appendNull(); 7        int len = str.length(); 8        ensureCapacityInternal(count + len); 9        str.getChars(0, len, value, count); 10       count += len; 11       return this; 12   } 13   private void ensureCapacityInternal(int minimumCapacity) {
14       // overflow-conscious code 15       if (minimumCapacity - value.length > 0) {
16           value = Arrays.copyOf(value,newCapacity(minimumCapacity)); 17       } 18   } 19   // ...省略... 20 }

          这里可以看出,Appendable 为抽象建造者,定义了建造方法,StringBuilder 既充当指挥者角色,又充当产品角色,又充当具体建造者,建造方法的实现由 AbstractStringBuilder 完成,而 StringBuilder 继承了 AbstractStringBuilder。

       2、myBatis 中的建造者模式

   org.apache.ibatis.session 包下的 SqlSessionFactoryBuilder 类,如下图 5-2 所示:

图 5-2

         里边很多重载的 build 方法,返回值都是 SqlSessionFactory,除了最后两个所有的 build最后都调用下面这个 build 方法:

1   public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
2       SqlSessionFactory var5; 3       try {
4           XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); 5           var5 = this.build(parser.parse()); 6       } catch (Exception var14) {
7           throw ExceptionFactory.wrapException("Error building SqlSession.", var14); 8       } finally {
9           ErrorContext.instance().reset(); 10          try {
11              reader.close(); 12          } catch (IOException var13) {
13               14          } 15      } 16      return var5; 17  }

          其中最重要的是 XMLConfigBuilder 的 parse 方法,代码如下:

1   public class XMLConfigBuilder extends BaseBuilder {
2    public Configuration parse() {
3        if (this.parsed) {
4            throw new BuilderException("Each XMLConfigBuilder can only be used once."); 5        } else {
6            this.parsed = true; 7            this.parseConfiguration(this.parser.evalNode("/configuration")); 8            return this.configuration; 9        } 10   } 11   private void parseConfiguration(XNode root) {
12       try {
13           Properties settings = this.settingsAsPropertiess(root.evalNode("settings")); 14           this.propertiesElement(root.evalNode("properties")); 15           this.loadCustomVfs(settings); 16           this.typeAliasesElement(root.evalNode("typeAliases")); 17         this.pluginElement(root.evalNode("plugins")); 18           this.objectFactoryElement(root.evalNode("objectFactory")); 19           this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); 20           this.reflectorFactoryElement(root.evalNode("reflectorFactory")); 21           this.settingsElement(settings); 22           this.environmentsElement(root.evalNode("environments")); 23           this.databaseIdProviderElement(root.evalNode("databaseIdProvider")); 24           this.typeHandlerElement(root.evalNode("typeHandlers")); 25           this.mapperElement(root.evalNode("mappers")); 26       } catch (Exception var3) {
27           throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3); 28       } 29   } 30   // ...省略... 31 }

   parse 方法最终要返回一个 Configuration 对象,构建 Configuration 对象的建造过程都在 parseConfiguration 方法中,这也就是 Mybatis 解析 XML配置文件 来构建 Configuration对象的主要过程

 

  参考:

   1、https://mp.weixin.qq.com/s?__biz=MzI1NDU0MTE1NA==&mid=2247483712&idx=1&sn=1ffd9837eb9413dde74ff509bf69ecc5&chksm=e9c2ed4ddeb5645b8cbf64c83d103a859ae49921c60e17fe8bebe63c26b04966be101d598848&scene=0#rd

   2、大话设计模式。

转载于:https://www.cnblogs.com/ITBlock/p/10090449.html

你可能感兴趣的文章
MySQL入门12-数据类型
查看>>
Windows Azure 保留已存在的虚拟网络外网IP(云服务)
查看>>
修改字符集
查看>>
HackTheGame 攻略 - 第四关
查看>>
js删除数组元素
查看>>
带空格文件名的处理(find xargs grep ..etc)
查看>>
华为Access、Hybrid和Trunk的区别和设置
查看>>
centos使用docker下安装mysql并配置、nginx
查看>>
关于HTML5的理解
查看>>
需要学的东西
查看>>
Internet Message Access Protocol --- IMAP协议
查看>>
Linux 获取文件夹下的所有文件
查看>>
对 Sea.js 进行配置(一) seajs.config
查看>>
第六周
查看>>
解释一下 P/NP/NP-Complete/NP-Hard 等问题
查看>>
javafx for android or ios ?
查看>>
微软职位内部推荐-Senior Software Engineer II-Sharepoint
查看>>
sql 字符串操作
查看>>
【转】Android布局优化之ViewStub
查看>>
网络安全管理技术作业-SNMP实验报告
查看>>