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

    【设计模式自习室】建造者模式

    前言
    《设计模式自习室》系列,顾名思义,本系列文章带你温习常见的设计模式。主要内容有:

    该设计模式的详细介绍,包括:
    引子,意图(大白话解释)
    类图,时序图(理论规范)
    该模式的代码示例:熟悉它长的样子
    该模式的实际使用案例:了解它在哪些重要的源码中出现过
    该系列会逐步更新于我的博客和公众号(博客见文章底部)

    也希望各位观众老爷能够关注我的个人公众号:后端技术漫谈,不会错过精彩好看的文章。

    系列文章回顾
    【设计模式自习室】开篇:为什么我们要用设计模式?

    创建型:建造者模式 Builder
    引子
    根据中文翻译的不同,建造者模式又可以称为生成器模式,它属于创建型模式。

    复杂对象相当于一辆有待建造的汽车,而对象的属性相当于汽车的部件,建造产品的过程就相当于组合部件的过程。由于组合部件的过程很复杂,因此,这些部件的组合过程往往被“外部化”到一个称作建造者的对象里,建造者返还给客户端的是一个已经建造完毕的完整产品对象,而用户无须关心该对象所包含的属性以及它们的组装方式,这就是建造者模式的模式动机。

    我们常用的StringBuilder就是一个建造者模式的典型例子

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

    类图
    如果看不懂UML类图,可以先粗略浏览下该图,想深入了解的话,可以继续谷歌,深入学习:

    建造者模式包含如下角色:

    Builder:抽象建造者 (我们经常会看到AbstractXXXX类)
    ConcreteBuilder:具体建造者
    Director:指挥者
    Product:产品角色
    下图是建造者模式得到UML图,可以看到:

    ConcreteBuilder是Builder的实现关系
    Builder聚合到Director上,因为Director还可以干别的事情


    时序图
    时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的。时序图中显示的是参与交互的对象及其对象之间消息交互的顺序。

    我们可以大致浏览下时序图,如果感兴趣的小伙伴可以去深究一下:

    实现
    1. 建造一个水杯
    一水杯工厂要生产各式各样的水杯,无论杯子是神马造型,但都包括绳子,帽子和杯体。以此模型创建各种类型的杯子。

    cup–>Product类

    public class Cup {

        private String string;    //绳子
        private String cap;       //帽子
        private String cupBody;   //杯体

        public void setString(String string) {
            this.string = string;
        }
        public void setCap(String cap) {
            this.cap = cap;
        }
        public void setCupBody(String cupBody) {
            this.cupBody = cupBody;
        }

        public void show() {
            System.out.println("杯子生产完毕");
        }

    }

    Builder–>Builder类

    public abstract class  Builder {

        protected Cup cup = new Cup();
        
        public abstract void buildString();
        
        public abstract void buildCap();
        
        public abstract void buildCupBody();
        
        public  Cup getResult() {
            return cup;
        }

    }

    ClassCup–>concrateBuilder类

    public class ClassCup extends Builder {

        @Override
        public void buildString() {
            cup.setString("生产绳子...");
            System.out.println("生产绳子...");
        }

        @Override
        public void buildCap() {
            cup.setCap("生产帽子...");
            System.out.println("生产帽子...");
        }

        @Override
        public void buildCupBody() {
            cup.setCupBody("生产杯体...");
            System.out.println("生产杯体...");
        }


    }

    Director类

    public class Director {

        private Builder builder;

        public Director(Builder builder) {
            this.builder = builder;
        }

        public void create() {
            builder.buildString();
            builder.buildCap();
            builder.buildCupBody();
            builder.getResult().show();
        }

        public static void main(String[] args) {
            Director d = new Director(new ClassCup());
            d.create();
        }

    }

    2. 编写一个简易的java.lang.StringBuilder
    AbstractStringBuilder–>Builder类

    public class AbstractStringBuilder {
        protected char[] value;

        protected int count;

        public AbstractStringBuilder(int capacity) {
            count = 0;
            value = new char[capacity];
        }

        public AbstractStringBuilder append(char c) {
            ensureCapacityInternal(count + 1);
            value[count++] = c;
            return this;
        }

        private void ensureCapacityInternal(int minimumCapacity) {
            // overflow-conscious code
            if (minimumCapacity - value.length > 0)
                expandCapacity(minimumCapacity);
        }

        void expandCapacity(int minimumCapacity) {
            int newCapacity = value.length * 2 + 2;
            if (newCapacity - minimumCapacity < 0)
                newCapacity = minimumCapacity;
            if (newCapacity < 0) {
                if (minimumCapacity < 0) // overflow
                    throw new OutOfMemoryError();
                newCapacity = Integer.MAX_VALUE;
            }
            value = Arrays.copyOf(value, newCapacity);
        }
    }

    StringBuilder–>concrateBuilder类

    public class StringBuilder extends AbstractStringBuilder {
        public StringBuilder() {
            super(16);
        }

        @Override
        public String toString() {
            // Create a copy, don't share the array
            return new String(value, 0, count);
        }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Client–>Director类

    public class Client {
        public static void main(String[] args) {
            StringBuilder sb = new StringBuilder();
            final int count = 26;
            for (int i = 0; i < count; i++) {
                sb.append((char) ('a' + i));
            }
            System.out.println(sb.toString());
        }
    }

    优缺点
    优点
    在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
    每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
    可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
    增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
    缺点
    建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
    如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
    使用场景举例
    JDK中使用
    java.lang.StringBuilder
    java.nio.ByteBuffer
    java.lang.StringBuffer
    java.lang.Appendable
    Apache Camel builders
    参考
    https://blog.csdn.net/c275046758/article/details/50540789

    https://github.com/CyC2018/CS-Notes/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%20-%20%E7%94%9F%E6%88%90%E5%99%A8.md

    https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/builder.html

    关注我
    我是一名后端开发工程师。

    主要关注后端开发,数据安全,爬虫,物联网,边缘计算等方向,欢迎交流。

    各大平台都可以找到我
    微信公众号:后端技术漫谈
    Github:@qqxx6661
    CSDN:@Rude3Knife
    知乎:@Zhendong
    简书:@蛮三刀把刀
    掘金:@蛮三刀把刀
    原创博客主要内容
    Java面试知识点复习全手册
    设计模式/数据结构 自习室
    Leetcode/剑指offer 算法题解析
    SpringBoot/SpringCloud菜鸟入门实战系列
    爬虫相关技术文章
    后端开发相关技术文章
    逸闻趣事/好书分享/个人兴趣
    个人公众号:后端技术漫谈


    如果文章对你有帮助,不妨收藏,投币,转发,在看起来~
    ————————————————
    版权声明:本文为CSDN博主「Rude3knife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qqxx6661/article/details/103687437

  • 相关阅读:
    .NET拾忆:FileSystemWatcher 文件监控
    .NET拾忆:EventLog(Windows事件日志监控)
    MSSqlServer 主从同步复制原理(发布/订阅)
    MSSqlServer 发布/订阅配置(主从同步)
    Entity Framework Code First(Mysql)
    .Net拾忆:Asp.net请求管道
    http://blog.csdn.net/dianhuiren/article/details/7543886 该作者对操作系统底层研究较深
    page cache 与 page buffer 转
    linux free命令中buffer与cache的区别
    Nginx重写规则指南 转
  • 原文地址:https://www.cnblogs.com/grj001/p/12223069.html
Copyright © 2011-2022 走看看