JAVA设计模式之建造者模式

Posted itblock

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA设计模式之建造者模式相关的知识,希望对你有一定的参考价值。

一、定义

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

  

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

技术分享图片

图 1-1 

二、实例展示

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

1 public class Product{
2 List<String> parts = new ArrayList<String>(); 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   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 @override 4 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 @override 4 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)每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。由于指挥者类针对抽                    象建造者编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便,符合 "开闭原则"。

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

 

      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、大话设计模式。
































































































































以上是关于JAVA设计模式之建造者模式的主要内容,如果未能解决你的问题,请参考以下文章

java设计模式之-建造者模式

Java设计模式之(建造者模式)

JAVA设计模式之建造者模式

JAVA设计模式之建造者模式

Java设计模式之建造者模式(Builder Pattern)

Java设计模式之建造者模式(Builder Pattern)