zoukankan      html  css  js  c++  java
  • 堆积木,建造者模式

    0x01:建造者模式简介

    将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

    假如一个对象的构建很复杂,需要很多步骤。则可以使用建造者模式,将其构建对象和组装成一个对象这两步给分开来。构建部分为(Builder)和组织部分(Director),实现了构建和装配的解耦。


    主要角色如下:

    Builder:为创建一个产品对象的各个部件指定抽象接口,一般由子类实现;

    ConcreteBuilder:具体建造者,实现抽象类定义的所有方法,并且返回一个组建好的产品对象;

    Director:为指挥者 / 导演类,负责安排已有模块的组装顺序,然后告诉Builder开始建造;

    Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

    0x02:建造者模式实现

    Product:要被构建的产品

    public class Product {
    
        private List<String> parts = new ArrayList<String>();
    
        public void addPart(String part) {
            parts.add(part);
        }
    
        public void show(){
            if(!parts.isEmpty()){
                parts.forEach(e -> {
                    System.out.println( e );
                });
            }
        }
    
    }
    

    Director:调用具体建造者进行产品构建

    public class Director {
    
        public void construct(Builder builder) {
            builder.buildPartA();
            builder.buildPartB();
        }
    
    }
    

    Builder:建造者抽象接口

    public interface Builder {
    
         void buildPartA();        //产品的A部件
    
         void buildPartB();        //产品的B部件
    
         Product getResult();    //组装产品建造后的结果
    
    }
    

    具体建造者ConcreteBuilder:有几个产品类就有几个具体的建造者,而且这多个产品类具有相同的接口或抽象类。

    public class ConcreteBuilder1 implements Builder {
    
        private Product product = new Product();
    
        //设置产品零件
        @Override
        public void buildPartA() {
            product.addPart("ConcreteBuilder1>>部件A");
        }
    
        @Override
        public void buildPartB() {
            product.addPart("ConcreteBuilder1>>部件B");
        }
    
        //组建一个产品
        @Override
        public Product getResult() {
            return product;
        }
    
    }
    
    public class ConcreteBuilder2 implements Builder {
    
        private Product product = new Product();
    
        //设置产品零件
        @Override
        public void buildPartA() {
            product.addPart("ConcreteBuilder2>>部件A");
        }
    
        @Override
        public void buildPartB() {
            product.addPart("ConcreteBuilder2>>部件B");
        }
    
        //组建一个产品
        @Override
        public Product getResult() {
            return product;
        }
    
    }
    

    建造者模式测试代码

    public class Client {
    
        public static void main(String[] args) {
    
            Director director = new Director();
            Builder builder1 = new ConcreteBuilder1();
            Builder builder2 = new ConcreteBuilder2();
    
            //指挥者用ConcreteBuilder1的方法来建造产品
            director.construct(builder1);
            Product product1 = builder1.getResult();
            product1.show();
    
            //指挥者用ConcreteBuilder2的方法来建造产品
            director.construct(builder2);
            Product product2 = builder2.getResult();
            product2.show();
    
        }
    
    }
    

    可以看出建造者模式具有以下特点:

    良好的封装性:建造者对客户端屏蔽了产品内部组成的细节,客户端不用关心每一个具体的产品内部是如何实现的。

    符合开闭原则

    便于控制细节风险:由于建造者是相互独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

    0x03:建造者模式在JDK中运用

    在JDK中,最经典的建造者模式的运用是StringBuilder和StringBuffer,这两个类最主要的区别就是StringBuilder线程不安全,StringBuffer线程安全。下面与StringBuilder源码讲解一下,建造者模式在JDK中的运用。

    Appendable 接口定义了多个 append 方法(抽象方法),即 Appendable 为抽象建造者(Builder),定义了抽象方法

    public interface Appendable {
    
        Appendable append(CharSequence csq) throws IOException;
    
        Appendable append(CharSequence csq, int start, int end) throws IOException;
    
        Appendable append(char c) throws IOException;
    }
    

    AbstractStringBuilder 实现了 Appendable 接口方法所有append()方法,俨然AbstractStringBuilder 已经是就建造者,只是是一个抽象类AbstractStringBuilder ,不能实例化

    abstract class AbstractStringBuilder implements Appendable, CharSequence {
    
        @Override
        public AbstractStringBuilder append(CharSequence s) {
            if (s == null)
                return appendNull();
            if (s instanceof String)
                return this.append((String)s);
            if (s instanceof AbstractStringBuilder)
                return this.append((AbstractStringBuilder)s);
    
            return this.append(s, 0, s.length());
        }
    
        @Override
        public AbstractStringBuilder append(CharSequence s, int start, int end) {
            if (s == null)
                s = "null";
            if ((start < 0) || (start > end) || (end > s.length()))
                throw new IndexOutOfBoundsException(
                    "start " + start + ", end " + end + ", s.length() "
                    + s.length());
            int len = end - start;
            ensureCapacityInternal(count + len);
            for (int i = start, j = count; i < end; i++, j++)
                value[j] = s.charAt(i);
            count += len;
            return this;
        }
    
       @Override
        public AbstractStringBuilder append(char c) {
            ensureCapacityInternal(count + 1);
            value[count++] = c;
            return this;
        }
    
        // 省略
    }
    

    StringBuilder 既充当了指挥者角色(Director),同时也充当了具体的建造者(ConcreteBuilder),建造方法的实现是由 AbstractStringBuilder 完成,而 StringBuilder 继承了 AbstractStringBuilder

    public final class StringBuilder
        extends AbstractStringBuilder
        implements java.io.Serializable, CharSequence
    {
    
       @Override
        public StringBuilder append(String str) {
            super.append(str);
            return this;
        }
    
        //其他省略
    
    }
    

    从StringBuilder代码上看,大部分方法都继承与AbstractStringBuilder,虽然是重写,但是还是直接调用了AbstractStringBuilder类中非方法,只是返回对象不太一样,StringBuilder类返回的对象就是当前创建的对象this本身(Product)。

    另外,MyBatis框架中也大量使用建造者模式,如果想了解MyBatis框架中什么运用建造者模式的,可以阅读下MyBatis的源码。

  • 相关阅读:
    软件工程作业3.28
    毕业论文管理系统建模图
    软件工程建模图作业
    酒店管理系统
    闪屏和功能引导页面代码编写
    Android算法编程代码
    3.28软件工程作业
    毕业论文管理系统
    图书管理系统建模图
    酒店预订系统故事
  • 原文地址:https://www.cnblogs.com/happyhuangjinjin/p/14249871.html
Copyright © 2011-2022 走看看