• 创建性-构造者设计模式


    前言

          我们在使用Retrofit等这些第三方框架的时候,发现他们的使用都很方便,比如Retrofit retrofit = new Retrofit.Builder().build(),和我们通常直接new一个对象不同,他是交给Builder类,通过build()函数来构造一个Retrofit对象。

          刚开始使用,可能不太明白,明明可以直接new出来,为什么要交给Builder来构造呢?那么通过学习了构造者设计模式,才明白,原来当使用者构造对象时,构造函数的参数一般大于等于五个,就可以考虑使用构造者设计模式,这样编写代码的好处,在于结构清晰,也易于扩展。

         在实际工作中,我们可能接触了很多这种链式创建对象的场景,比如AlertDialog,发现这种代码在使用的时候,真的很香,不仅实现了参数传递的灵活性,也避免了因参数过多造成的混乱。总之,除了使用官方封装的这些类以外,自己在实现代码的同时,也想要动手实现一个建造者设计模式。

     实现

        下面我们以电脑为例,创建一个抽象类Computer,我们想想,电脑都有什么属性,品牌,型号,操作系统,用途,类型,名字等等。这些属性如果都用构造方法实现的话,会很长,而且也不易于扩展,不够灵活。

    1. static class Computer{
    2. String name;
    3. String brand;
    4. String os;
    5. String display;
    6. String type;
    7. String use;
    8. public void setName(String name) {
    9. this.name = name;
    10. }
    11. public void setBrand(String brand) {
    12. this.brand = brand;
    13. }
    14. public void setOs(String os) {
    15. this.os = os;
    16. }
    17. public void setDisplay(String display) {
    18. this.display = display;
    19. }
    20. public void setType(String type) {
    21. this.type = type;
    22. }
    23. public void setUse(String use) {
    24. this.use = use;
    25. }
    26. }

         比如,我们需要创造一个macbook笔记本,用传统思维,直接创造一个类,然后继承Computer,通过构造函数的方法重载,完成各种需求的笔记本。这样一套下来,代码臃肿不说,也不宜与后期的维护,如果有新的属性,又要重载一个构造函数,比较繁琐。

    1. static class MacBook extends Computer{
    2. public MacBook() {
    3. }
    4. // ……
    5. //各种构造函数
    6. // ……
    7. @Override
    8. public String toString() {
    9. return "MacBook{" +
    10. "name='" + name + '\'' +
    11. ", brand='" + brand + '\'' +
    12. ", os='" + os + '\'' +
    13. ", display='" + display + '\'' +
    14. ", type='" + type + '\'' +
    15. ", use='" + use + '\'' +
    16. '}';
    17. }
    18. }

        如果有一个专门的类,来创建不同需求的笔记本,这个问题就能很好的解决。

        那么这个专门的类就是Builder类,通过构造者设计模式进行优化,我们这里具体到了MacBook笔记本,在实际开发工作中,这个可以使用泛型T代替,更加灵活。

    1. static abstract class Builder {
    2. abstract MacBookBuilder builderName(String name);
    3. abstract MacBookBuilder builderBrand(String brand);
    4. abstract MacBookBuilder builderOs(String os);
    5. abstract MacBookBuilder builderType(String type);
    6. abstract MacBookBuilder builderUse(String use);
    7. abstract MacBookBuilder builderDisPlay(String display);
    8. abstract Computer build();
    9. }

      接下来,我们将利用MacBookBuilder 来构造笔记本,代码如下:

    1. static class MacBookBuilder extends Builder{
    2. MacBook macBook = new MacBook();
    3. @Override
    4. MacBookBuilder builderName(String name) {
    5. macBook.name = name;
    6. return this;
    7. }
    8. @Override
    9. MacBookBuilder builderBrand(String brand) {
    10. macBook.brand = brand;
    11. return this;
    12. }
    13. @Override
    14. MacBookBuilder builderOs(String os) {
    15. macBook.os = os;
    16. return this;
    17. }
    18. @Override
    19. MacBookBuilder builderType(String type) {
    20. macBook.type = type;
    21. return this;
    22. }
    23. @Override
    24. MacBookBuilder builderUse(String use) {
    25. macBook.use = use;
    26. return this;
    27. }
    28. @Override
    29. MacBookBuilder builderDisPlay(String display) {
    30. macBook.display = display;
    31. return this;
    32. }
    33. @Override
    34. Computer build() {
    35. return macBook;
    36. }
    37. }

    好了,我们通过测试类,测试一下,附上完整代码:

    1. package com.example.lib;
    2. public class BuilderTest {
    3. public static void main(String[] args) {
    4. Computer macbook = new MacBookBuilder()
    5. .builderName("macbook 2023")
    6. .builderOs("mac/os")
    7. .builderBrand("apple")
    8. .builderType("Laptops")
    9. .builderDisPlay("Retina显示器")
    10. .builderUse("studyProgram")
    11. .build();
    12. System.out.println(macbook.toString());
    13. }
    14. static class Computer{
    15. String name;
    16. String brand;
    17. String os;
    18. String display;
    19. String type;
    20. String use;
    21. public void setName(String name) {
    22. this.name = name;
    23. }
    24. public void setBrand(String brand) {
    25. this.brand = brand;
    26. }
    27. public void setOs(String os) {
    28. this.os = os;
    29. }
    30. public void setDisplay(String display) {
    31. this.display = display;
    32. }
    33. public void setType(String type) {
    34. this.type = type;
    35. }
    36. public void setUse(String use) {
    37. this.use = use;
    38. }
    39. }
    40. static class MacBook extends Computer{
    41. public MacBook() {
    42. }
    43. @Override
    44. public String toString() {
    45. return "MacBook{" +
    46. "name='" + name + '\'' +
    47. ", brand='" + brand + '\'' +
    48. ", os='" + os + '\'' +
    49. ", display='" + display + '\'' +
    50. ", type='" + type + '\'' +
    51. ", use='" + use + '\'' +
    52. '}';
    53. }
    54. }
    55. static abstract class Builder {
    56. abstract MacBookBuilder builderName(String name);
    57. abstract MacBookBuilder builderBrand(String brand);
    58. abstract MacBookBuilder builderOs(String os);
    59. abstract MacBookBuilder builderType(String type);
    60. abstract MacBookBuilder builderUse(String use);
    61. abstract MacBookBuilder builderDisPlay(String display);
    62. abstract Computer build();
    63. }
    64. static class MacBookBuilder extends Builder{
    65. MacBook macBook = new MacBook();
    66. @Override
    67. MacBookBuilder builderName(String name) {
    68. macBook.name = name;
    69. return this;
    70. }
    71. @Override
    72. MacBookBuilder builderBrand(String brand) {
    73. macBook.brand = brand;
    74. return this;
    75. }
    76. @Override
    77. MacBookBuilder builderOs(String os) {
    78. macBook.os = os;
    79. return this;
    80. }
    81. @Override
    82. MacBookBuilder builderType(String type) {
    83. macBook.type = type;
    84. return this;
    85. }
    86. @Override
    87. MacBookBuilder builderUse(String use) {
    88. macBook.use = use;
    89. return this;
    90. }
    91. @Override
    92. MacBookBuilder builderDisPlay(String display) {
    93. macBook.display = display;
    94. return this;
    95. }
    96. @Override
    97. Computer build() {
    98. return macBook;
    99. }
    100. }
    101. }

    总结 

    构造者设计模式,在安卓开放当中非常常见,也是一种创建型设计模式,类似与工厂模式,但不同于工厂模式。主要优点如下:

    • 客户端不需要理解产品的内部细节,完成了产品本身与产品创建的解耦
    • 每一个具体的建造者都相对独立,产品的创建更加的精细化
    • 增加新的具体建造者,无需修改原有的代码,符合开闭原则
    • 使用链式编程,代码上更加美观

  • 相关阅读:
    杂想之一个C++内存泄露案例
    SSM整合完整流程讲解
    Qt 中 connect 函数实现信号与槽函数的连接
    Spring Boot 项目的 pom.xml 中,groupId、artifactId 等信息要如何定义?——定义规则及案例
    想要精通算法和SQL的成长之路 - 跳跃游戏系列
    【刷题心得】双指针法|HashSet<T>
    flutter 合并数组及操作符
    大厂招聘IO常问面试题
    C语言之练习题
    XSS进阶一
  • 原文地址:https://blog.csdn.net/qq_34123324/article/details/132644096