zoukankan      html  css  js  c++  java
  • 创建型设计模式 -- 建造者模式

    一、小案例分析

    1、功能需求:

      现需要建房子,建房流程:挖地基、砌墙、封顶。对于不同种类的房子(高楼,别墅),流程虽然一样,但是具体功能实现不同。如何实现建房子?

    2、小菜鸡的答案:

    (1)定义一个抽象接口,并定义三个抽象方法(挖地基、砌墙、封顶)。
    (2)对于不同种类的房子,实现该接口,并重写相关方法即可。
    (3)代码实现:

    package builder.pattern;
    
    /**
     * 测试类
     *
     */
    public class BuilderDemo {
        public static void main(String[] args) {
            System.out.println("建别墅流程:");
            BuilderHouse villa = new Villa();
    
            System.out.println("
    建高楼流程");
            BuilderHouse highBuild = new HighBuild();
        }
    }
    
    /**
     * 定义一个建房子的接口,并定义其流程
     */
    interface BuilderHouse {
        void scoopHole(); // 挖地基
    
        void buildWall(); // 砌墙
    
        void topOff(); // 封顶
    }
    
    /**
     * 建别墅,实现建房子的接口
     *
     */
    class Villa implements BuilderHouse {
        /**
         * 建别墅流程
         */
        public Villa() {
            scoopHole();
            buildWall();
            topOff();
        }
    
        @Override
        public void scoopHole() {
            System.out.println("挖10米地基");
        }
    
        @Override
        public void buildWall() {
            System.out.println("砌10层墙");
        }
    
        @Override
        public void topOff() {
            System.out.println("楼顶建个游泳池");
        }
    }
    
    /**
     * 建高楼流程,实现建房子的接口
     *
     */
    class HighBuild implements BuilderHouse {
        /**
         * 建高楼流程
         */
        public HighBuild() {
            scoopHole();
            buildWall();
            topOff();
        }
    
        @Override
        public void scoopHole() {
            System.out.println("挖30米地基");
        }
    
        @Override
        public void buildWall() {
            System.out.println("砌60层墙");
        }
    
        @Override
        public void topOff() {
            System.out.println("楼顶建个停机坪");
        }
    }

    (4)代码分析:
      容易理解并操作,但是程序的扩展性不好,且耦合性强(将产品与创建产品的过程封装在一起)。
    (5)UML图

    二、建造者模式

    1、什么是建造者模式

      又叫生成器模式,其将复杂的对象的建造过程抽象出来,并在其子类中去实现不同的建造。用户只需要去调用就行,不需要管建造的内部细节如何实现。简单的理解为,将一堆零件拼成一个整体,而零件是抽象的,并由不同的子类去实现,用户不需要管零件是如何形成的,能组装就行。

    2、建造者模式的核心角色

    (1)产品(Product):一个具体的产品对象。
    (2)抽象建造者(Builder):定义一个接口或抽象类,内部定义生成产品各个零件的抽象方法。
    (3)具体建造者(ConcreateBuilder):实现接口,并重写生成各零件的方法。
    (4)组装者(Commander):按照流程拼接零件,并返回一个对象。
    (5)代码实现:

    package builder.pattern;
    
    /**
     * 测试类
     *
     */
    public class BuilderDemo {
        public static void main(String[] args) {
            System.out.println("建别墅流程:");
            HouseBuilder villaBuilder = new VillaBuilder();
            HouseCommandar villaCommandar = new HouseCommandar(villaBuilder);
            System.out.println(villaCommandar.createHouse());
    
            System.out.println("
    建高楼流程");
            HouseBuilder highBuildBuilder = new HighBuildBuilder();
            HouseCommandar highBuildCommandar = new HouseCommandar(highBuildBuilder);
            System.out.println(highBuildCommandar.createHouse());
        }
    }
    
    /**
     * 产品类
     *
     */
    class House {
        private String basis;
        private String wall;
        private String roof;
    
        public String getBasis() {
            return basis;
        }
    
        public void setBasis(String basis) {
            this.basis = basis;
        }
    
        public String getWall() {
            return wall;
        }
    
        public void setWall(String wall) {
            this.wall = wall;
        }
    
        public String getRoof() {
            return roof;
        }
    
        public void setRoof(String roof) {
            this.roof = roof;
        }
    
        @Override
        public String toString() {
            return "House [basis=" + basis + ", wall=" + wall + ", roof=" + roof + "]";
        }
    }
    
    /**
     * 抽象建造者,内部定义生成产品各个零件的抽象方法。
     *
     */
    abstract class HouseBuilder {
        House house = new House();
    
        public abstract void scoopHole(); // 挖地基
    
        public abstract void buildWall(); // 砌墙
    
        public abstract void topOff(); // 封顶
    
        public House getHouse() {
            return house;
        }
    }
    
    /**
     * 具体建造者,建别墅,继承抽象类,并重写相关方法
     *
     */
    class VillaBuilder extends HouseBuilder {
        @Override
        public void scoopHole() {
            house.setBasis("挖10米地基");
        }
    
        @Override
        public void buildWall() {
            house.setWall("砌10层墙");
        }
    
        @Override
        public void topOff() {
            house.setRoof("楼顶建个游泳池");
        }
    }
    
    /**
     * 建高楼流程,实现建房子的接口
     *
     */
    class HighBuildBuilder extends HouseBuilder {
    
        @Override
        public void scoopHole() {
            house.setBasis("挖30米地基");
        }
    
        @Override
        public void buildWall() {
            house.setWall("砌60层墙");
        }
    
        @Override
        public void topOff() {
            house.setRoof("楼顶建个停机坪");
        }
    }
    
    /**
     * 组装者,控制零件组合流程,并返回一个产品对象
     */
    class HouseCommandar {
        private HouseBuilder houseBuilder;
    
        /**
         * 获取具体的建造者
         */
        public HouseCommandar(HouseBuilder houseBuilder) {
            this.houseBuilder = houseBuilder;
        }
    
        /**
         * 控制建房流程,并返回一个房子实例
         * 
         * @return 房子实例
         */
        public House createHouse() {
            houseBuilder.scoopHole();
            houseBuilder.buildWall();
            houseBuilder.topOff();
            return houseBuilder.getHouse();
        }
    }

    (6)代码分析:
      相比于上例,其将控制产品流程的代码抽出来了。使产品与产品构建流程分离,从而在一定程度上解耦。当扩展代码时,只需继承HouseBuilder 并重写相关方法即可。
    (7)UML图:

    3、抽象工厂模式与建造者模式的区别

    (1)抽象工厂模式是根据不同的工厂去创建一个对象。
    (2)建造者模式是根据流程去组装一个对象。


    三、JDK源码分析(StringBuilder)

    1、部分源码

    public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
        
    }
    
    abstract class AbstractStringBuilder implements Appendable, CharSequence{
        //内部定义了一系列方法,且部分方法返回值类型为AbstractStringBuilder 
        public AbstractStringBuilder append(String str) {
            if (str == null)
                return appendNull();
            int len = str.length();
            ensureCapacityInternal(count + len);
            str.getChars(0, len, value, count);
            count += len;
            return this;
        }
         public AbstractStringBuilder deleteCharAt(int index) {
            if ((index < 0) || (index >= count))
                throw new StringIndexOutOfBoundsException(index);
            System.arraycopy(value, index+1, value, index, count-index-1);
            count--;
            return this;
        }
    } 

    2、源码分析

      AbstractStringBuilder 内部定义了一系列返回值类型为AbstractStringBuilder 的方法,这些方法可以组合起来,形成链式调用(产品构建流程),根据链式调用来组装成最后返回的对象。
    即StringBuilder 是组装者与具体建造者。AbstractStringBuilder 是抽象建造者。
      

  • 相关阅读:
    CSS BEM 命名规范简介
    React 端的编程范式
    在React应用程序中用RegEx测试密码强度
    React 中获取数据的 3 种方法及它们的优缺点
    vue props传值常见问题
    如何理解vue中的v-model?
    利用jQuery not()方法选取除某个元素外的所有元素
    初识Nest.js
    react-绑定this并传参的三种方式
    Angular怎么防御xss攻击?
  • 原文地址:https://www.cnblogs.com/l-y-h/p/11360427.html
Copyright © 2011-2022 走看看