zoukankan      html  css  js  c++  java
  • 「补课」进行时:设计模式(4)——建造者模式

    1. 前文汇总

    「补课」进行时:设计模式系列

    2. 建造者模式定义

    建造者模式(Builder Pattern)也叫做生成器模式,其定义如下:

    Separate the construction of a complex object from its representation sothat the same construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)

    通用类图:

    • Product: 产品类,通常是实现了模板方法模式,也就是有模板方法和基本方法。
    • Builder: 抽象建造者,规范产品的组建,一般是由子类实现。
    • ConcreteBuilder: 具体建造者,实现抽象类定义的所有方法,并且返回一个组建好的对象。
    • Director: 导演类,负责安排已有模块的顺序,然后告诉 Builder 开始建造。

    通用代码示例:

    Product 产品类:

    public class Product {
        public void doSomething() {
            // 业务处理
        }
    }
    

    Builder 抽象建造者:

    public abstract class Builder {
        // 设置产品不同的部分,用来获得不同的产品
        abstract void setPart();
        // 建造产品
        abstract Product buildProduct();
    }
    

    ConcreteBuilder 具体建造者:

    public class ConcreteProduct extends Builder{
        private Product product = new Product();
        @Override
        void setPart() {
            // 独特的处理逻辑
        }
    
        @Override
        Product buildProduct() {
            return product;
        }
    }
    

    Director 导演类:

    public class Director {
        private Builder builder = new ConcreteProduct();
        public Product getProduct() {
            builder.setPart();
            // 设置不同的 part ,生产不同的零件
            return builder.buildProduct();
        }
    }
    

    3. 通过建造者模式造一辆共享单车

    接下来使用建造者模式造一辆共享单车。

    经历过共享单车大战之后,现在共享单车还在运营活着的也没几家了,在大街上比较常看到的有美团单车和哈罗单车,先创建一个抽象的产品类:

    public abstract class AbstractBike {
        // 各个零件制造顺序
        private ArrayList<String> sequence = new ArrayList<> ();
        // 自行车车架
        protected abstract void frame();
        // 自行车座位
        protected abstract void seat();
        // 自行车轮子
        protected abstract void tire();
        // 生产方法
        final public void createBike() {
            for (int i = 0; i < sequence.size(); i++) {
                String actionName = this.sequence.get(i);
                if (actionName.equalsIgnoreCase("frame")) {
                    this.frame();
                } else if (actionName.equalsIgnoreCase("seat")) {
                    this.seat();
                } else if (actionName.equalsIgnoreCase("tire")) {
                    this.tire();
                }
            }
        }
    
        final public void setSequence(ArrayList sequence) {
            this.sequence = sequence;
        }
    }
    

    在这个产品类中,定义了三个零件和一个零件的制造顺序,在单车的生产方法中,通过循环制造顺序,可以制造的顺序进行控制。

    接下来是两个具体的产品类:

    public class HelloBike extends AbstractBike {
        @Override
        protected void frame() {
            System.out.println("现在开始生产一个哈罗车架");
        }
    
        @Override
        protected void seat() {
            System.out.println("现在开始生产一个哈罗座位");
        }
    
        @Override
        protected void tire() {
            System.out.println("现在开始生产两个哈罗轮胎");
        }
    }
    
    public class MeituanBike extends AbstractBike {
        @Override
        protected void frame() {
            System.out.println("现在开始生产一个美团车架");
        }
    
        @Override
        protected void seat() {
            System.out.println("现在开始生产一个美团座位");
        }
    
        @Override
        protected void tire() {
            System.out.println("现在开始生产两个美团轮胎");
        }
    }
    

    接下来创建一个抽象的 Builder :

    public abstract class Builder {
        // 创建一个生产顺序模型
        public abstract void setSequence(ArrayList<String> sequence);
        // 生产完成后获取这个车辆模型
        public abstract AbstractBike getBike();
    }
    

    然后是两个具体的建造者:

    public class HelloBuilder extends Builder {
        private HelloBike helloBike = new HelloBike();
        @Override
        public void setSequence(ArrayList<String> sequence) {
            this.helloBike.setSequence(sequence);
        }
    
        @Override
        public AbstractBike getBike() {
            return this.helloBike;
        }
    }
    
    public class MeituanBuilder extends Builder {
        private MeituanBike meituanBike = new MeituanBike();
        @Override
        public void setSequence(ArrayList<String> sequence) {
            this.meituanBike.setSequence(sequence);
        }
    
        @Override
        public AbstractBike getBike() {
            return this.meituanBike;
        }
    }
    

    最后是一个导演类:

    public class Director {
        private ArrayList<String> sequence = new ArrayList<>();
        private HelloBuilder helloBuilder = new HelloBuilder();
        private MeituanBuilder meituanBuilder = new MeituanBuilder();
    
        public HelloBike getHelloBike() {
            this.sequence.clear();
            // 自定义生产的顺序
            this.sequence.add("frame");
            this.sequence.add("seat");
            this.sequence.add("tire");
            this.helloBuilder.setSequence(sequence);
            return (HelloBike) this.helloBuilder.getBike();
        }
    
        public MeituanBike getMeituanBike() {
            this.sequence.clear();
            // 定义生产的顺序
            this.sequence.add("seat");
            this.sequence.add("tire");
            this.sequence.add("frame");
            this.meituanBuilder.setSequence(sequence);
            return (MeituanBike) this.meituanBuilder.getBike();
        }
    }
    

    然后写一个 Test 类进行一下测试:

    public class Test {
        public static void main(String[] args) {
            Director director = new Director();
            director.getHelloBike().createBike();
        }
    }
    

    运行结果是:

    现在开始生产一个哈罗车架
    现在开始生产一个哈罗座位
    现在开始生产两个哈罗轮胎
    

    最后放一个这个示例的 UML 类图:

  • 相关阅读:
    白盒测试相关内容总结
    黑盒测试相关内容总结
    int.parse的出错异常处理
    逃的过初一逃不过十五之三个输入框文本内容检测的实现及测试
    EditBox问题等价类划分
    关于课堂上Exercise#1的讨论
    js中关于事件处理函数名后面是否带括号的问题
    关于提升和作用域的一道有趣的题目
    绝对定位对元素宽度的影响
    js异步函数队列
  • 原文地址:https://www.cnblogs.com/babycomeon/p/13883486.html
Copyright © 2011-2022 走看看