创建性-构造者设计模式

前言

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

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

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

实现

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

java 复制代码
 static class Computer{
        String name;
        String brand;
        String os;
        String display;
        String type;
        String use;

        public void setName(String name) {
            this.name = name;
        }

        public void setBrand(String brand) {
            this.brand = brand;
        }

        public void setOs(String os) {
            this.os = os;
        }

        public void setDisplay(String display) {
            this.display = display;
        }

        public void setType(String type) {
            this.type = type;
        }

        public void setUse(String use) {
            this.use = use;
        }
    }

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

java 复制代码
    static class MacBook extends Computer{
        public MacBook() {
        }
        
        // ......
        //各种构造函数
        // ......        
 
        @Override
        public String toString() {
            return "MacBook{" +
                    "name='" + name + '\'' +
                    ", brand='" + brand + '\'' +
                    ", os='" + os + '\'' +
                    ", display='" + display + '\'' +
                    ", type='" + type + '\'' +
                    ", use='" + use + '\'' +
                    '}';
        }
    }

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

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

java 复制代码
 static abstract class Builder {
        abstract MacBookBuilder builderName(String name);

        abstract MacBookBuilder builderBrand(String brand);

        abstract MacBookBuilder builderOs(String os);

        abstract MacBookBuilder builderType(String type);

        abstract MacBookBuilder builderUse(String use);

        abstract MacBookBuilder builderDisPlay(String display);

        abstract Computer build();

    }

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

java 复制代码
 static class MacBookBuilder extends Builder{

        MacBook macBook = new MacBook();

       @Override
        MacBookBuilder builderName(String name) {
            macBook.name = name;
            return this;
        }

        @Override
        MacBookBuilder builderBrand(String brand) {
            macBook.brand = brand;
            return this;
        }

        @Override
        MacBookBuilder builderOs(String os) {
            macBook.os = os;
            return this;
        }

        @Override
        MacBookBuilder builderType(String type) {
            macBook.type = type;
            return this;
        }

        @Override
        MacBookBuilder builderUse(String use) {
            macBook.use = use;
            return this;
        }

        @Override
        MacBookBuilder builderDisPlay(String display) {
            macBook.display = display;
            return this;
        }

        @Override
        Computer build() {
            return macBook;
        }
    }

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

java 复制代码
package com.example.lib;


public class BuilderTest {

    public static void main(String[] args) {

        Computer macbook = new MacBookBuilder()
                .builderName("macbook 2023")
                .builderOs("mac/os")
                .builderBrand("apple")
                .builderType("Laptops")
                .builderDisPlay("Retina显示器")
                .builderUse("studyProgram")
                .build();

        System.out.println(macbook.toString());
    }


    static class Computer{
        String name;
        String brand;
        String os;
        String display;
        String type;
        String use;

        public void setName(String name) {
            this.name = name;
        }

        public void setBrand(String brand) {
            this.brand = brand;
        }

        public void setOs(String os) {
            this.os = os;
        }

        public void setDisplay(String display) {
            this.display = display;
        }

        public void setType(String type) {
            this.type = type;
        }

        public void setUse(String use) {
            this.use = use;
        }
    }


    static class MacBook extends Computer{
        public MacBook() {
        }

        @Override
        public String toString() {
            return "MacBook{" +
                    "name='" + name + '\'' +
                    ", brand='" + brand + '\'' +
                    ", os='" + os + '\'' +
                    ", display='" + display + '\'' +
                    ", type='" + type + '\'' +
                    ", use='" + use + '\'' +
                    '}';
        }
    }


    static abstract class Builder {
        abstract MacBookBuilder builderName(String name);

        abstract MacBookBuilder builderBrand(String brand);

        abstract MacBookBuilder builderOs(String os);

        abstract MacBookBuilder builderType(String type);

        abstract MacBookBuilder builderUse(String use);

        abstract MacBookBuilder builderDisPlay(String display);

        abstract Computer build();

    }

   static class MacBookBuilder extends Builder{

        MacBook macBook = new MacBook();

       @Override
        MacBookBuilder builderName(String name) {
            macBook.name = name;
            return this;
        }

        @Override
        MacBookBuilder builderBrand(String brand) {
            macBook.brand = brand;
            return this;
        }

        @Override
        MacBookBuilder builderOs(String os) {
            macBook.os = os;
            return this;
        }

        @Override
        MacBookBuilder builderType(String type) {
            macBook.type = type;
            return this;
        }

        @Override
        MacBookBuilder builderUse(String use) {
            macBook.use = use;
            return this;
        }

        @Override
        MacBookBuilder builderDisPlay(String display) {
            macBook.display = display;
            return this;
        }

        @Override
        Computer build() {
            return macBook;
        }
    }
}

总结

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

  • 客户端不需要理解产品的内部细节,完成了产品本身与产品创建的解耦
  • 每一个具体的建造者都相对独立,产品的创建更加的精细化
  • 增加新的具体建造者,无需修改原有的代码,符合开闭原则
  • 使用链式编程,代码上更加美观
相关推荐
In_life 在生活3 小时前
设计模式(四)装饰器模式与命令模式
设计模式
瞎姬霸爱.3 小时前
设计模式-七个基本原则之一-接口隔离原则 + SpringBoot案例
设计模式·接口隔离原则
鬣主任4 小时前
Spring设计模式
java·spring boot·设计模式
程序员小海绵【vincewm】6 小时前
【设计模式】结合Tomcat源码,分析外观模式/门面模式的特性和应用场景
设计模式·tomcat·源码·外观模式·1024程序员节·门面模式
丶白泽6 小时前
重修设计模式-行为型-命令模式
设计模式·命令模式
gjh120810 小时前
设计模式:工厂方法模式和策略模式
设计模式·工厂方法模式·策略模式
shinelord明11 小时前
【再谈设计模式】抽象工厂模式~对象创建的统筹者
数据结构·算法·设计模式·软件工程·抽象工厂模式
前端拾光者12 小时前
前端开发设计模式——责任链模式
设计模式·责任链模式
liang899913 小时前
设计模式之策略模式(Strategy)
设计模式·策略模式
马剑威(威哥爱编程)14 小时前
读写锁分离设计模式详解
java·设计模式·java-ee