美文网首页Android开发
30 Java设计模式系列-建造者(Build)模式

30 Java设计模式系列-建造者(Build)模式

作者: 凤邪摩羯 | 来源:发表于2021-01-24 12:12 被阅读0次

    建造者(Build)模式

    建造者(Build)模式是非常常见的设计模式之一,写个笔记,记录一下我的学习过程和心得。

    首先了解一些Build模式的定义。

    将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

    但是看完这个定义,并没有什么卵用,你依然不知道什么是Builder设计模式。在此个人的态度是学习设计模式这种东西,不要过度在意其定义,定义往往是比较抽象的,学习它最好的例子就是通过样例代码。

    我们通过一个例子来引出Builder模式。假设有一个Car类,我们通过该Car类来构建一大批汽车,这个Car类里有很多属性,最常见的比如颜色,价格,品牌,排量等等,并且我们允许这些值不被设置,也就是允许为null,该类的定义如下。

    public class Car  {
        Color color;
        double price;
        String brand;
        String displacement;
    
        public Color getColor() {
            return color;
        }
    
        public void setColor(Color color) {
            this.color = color;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public String getDisplacement() {
            return displacement;
        }
    
        public void setDisplacement(String displacement) {
            this.displacement = displacement;
        }
    }
    
    

    然后我们为了方便可能会定义一个构造方法。

    public Car(Color color, double price, String brand, String displacement) {
     this.color = color;
     this.price = price;
     this.brand = brand;
     this. displacement = displacement;
    }
    
    

    有时候,只想传部分参数,你还会定义如下类似的构造方法。

    public Car(Color color) {
     this.color = color;
    }
     public Car(Color color, double price) {
     this.color = color;
     this.price = price;
    }
     public Car(Color color, double price, String brand) {
    this.color = color;
     this.price = price;
     this.brand = brand;
    } 
    
    

    于是你就可以这样创建各个需要的对象

    Person p2=new Person(Color.read);
    Person p3=new Person(Color.blue,180000);
    Person p4=new Person(Color.green,21180, "小鹏");
    Person p5=new Person(Color.white,17170,"法拉利","4.0L"); 
    
    

    可以想象一下这样创建的坏处,如果四个参都是同一种数据类型,那各个参数到底是什么意思,那得考读性了,。还有一个问题就是当有很多参数时,编写这个构造数就会显得异常麻烦,这时候如果换一个角度,试试Builder模式,你会发现代码的可读性一下子就上去了。

    我们给Car增加一个静态内部类Builder类,并修改Car类的构造函数,代码如下。

    public class Car  {
        Color color;
        double price;
        String brand;
        String displacement;
    
        public Color getColor() {
            return color;
        }
    
        public void setColor(Color color) {
            this.color = color;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public String getDisplacement() {
            return displacement;
        }
    
        public void setDisplacement(String displacement) {
            this.displacement = displacement;
        }
    
        private Car(Builder builder) {
     this.color = builder.color;
     this.price = builder.price;
     this.brand = builder.brand;
     this. displacement = builder.displacement;
        }
    
        public static class Builder {
    
        Color color;
        double price;
        String brand;
        String displacement;
    
            public  Builder color(Color color){
                this.color=color;
                return  this;
            }
            public  Builder price(double price){
                this.price=price;
                return  this;
            }
            public  Builder brand(String brand){
                this.brand=brand;
                return  this;
            }
            public  Builder displacement(String displacement){
                this.displacement=displacement;
                return  this;
            }
    
            public Car build() {
                return new Car(this);
            }
        }
    }
    
    

    这样,我们就不会被Car类构造函数的各个入参搞得稀里糊涂了。
    此外Builder类中的成员函数返回Builder对象自身,让它支持链式调用,使代码可读性大大增强。于是我们就可以这样创建Car类。

    new Car.Builder().color(Color.BLUE)
                     .price(129800)
                     .pailiang("1.5T")
                     .brand("小鹏")
                     .build();
    
    

    有没有觉得创建过程一下子就变得那么清晰了。对应的值是什么属性一目了然,可读性大大增强。

    综上,我们总结一下build模式的要点:

    1. 定义一个静态内部类Builder,内部的成员变量和外部类一样
    2. Builder类通过一系列的方法用于成员变量的赋值,并返回当前对象本身(this)
    3. Builder类提供一个外部类的创建方法(build、create……),该方法内部调用了外部类的一个私有构造函数,入参就是内部类Builder
    4. 外部类提供一个私有构造函数供内部类调用,在该构造函数中完成成员变量的赋值,取值为Builder对象中对应的成变量的值

    模式应用广泛

    其实在Android中, Builder模式也是被大量的运用。比如常见的对话框的创建

    AlertDialog.Builder builder=new AlertDialog.Builder(this);
    AlertDialog dialog=builder.setTitle("标题")
     .setIcon(android.R.drawable.ic_dialog_alert)
     .setView(R.layout.myview)
     .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
     }
     })
     .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
     }
     })
     .create();
    dialog.show(); 
    
    

    而且,各个第三方框架也大量的运用了Builder模式
    如Gson中的GsonBuilder,代码太长了,就不贴了,有兴趣自己去看源码,这里只贴出其Builder的使用方法。

    GsonBuilder builder=new GsonBuilder();
    Gson gson=builder.setPrettyPrinting()
     .disableHtmlEscaping()
     .generateNonExecutableJson()
     .serializeNulls()
     .create(); 
    
    

    再看看著名的网络请求框架OkHttp

    Request.
    Builder builder=new Request.Builder();
    Request request=builder.addHeader("","")
     .url("")
     .post(body)
     .build();
    
    

    总结

    优点

    Builder模式通常作为配置类的构建器将配置的构建和表示分离开来,同时也是将配置从目标类中隔离出来,避免作为过多的setter方法,并且隐藏内部的细节。Builder模式比较常见的实现形式是通过链式调用,这样使得代码更加简洁、易懂。

    缺点

    内部类与外部类相互引用,可能会导致内存消耗比较大,不过鉴于现在的手机内存来讲,这点几乎影响不大。

    相关文章

      网友评论

        本文标题:30 Java设计模式系列-建造者(Build)模式

        本文链接:https://www.haomeiwen.com/subject/mymzoktx.html