builder模式的新学习

静态工厂和构造器有个共同的局限性:他们不能很好的扩展到大量的可选参数。大多数产品在牧歌可选与中都会有非零的值

对于这种类,应该使用哪种构造器或者静态方法来进行编写?程序员一般习惯采用重叠构造器(telescoping constructor)模式。在这种模式下,你可以第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,以此类推,最后一个构造器包含所有的可选参数。

public class NutritionFacts {
private final int servingSize; //required
private final int servings; //required
private final int calories; //optional
private final int fat; //optional
private final int sodium; //optional
private final int carbohydrate; //optional public NutritionFacts(int servingSize,int servings){
this(servingSize,servings,0);
}
public NutritionFacts(int servingSize,int servings,int calories){
this(servingSize,servings,calories,0);
}
public NutritionFacts(int servingSize,int servings,int calories,int fat){
this(servingSize,servings,calories,fat,0);
}
public NutritionFacts(int servingSize,int servings,int calories,int fat,int sodium){
this(servingSize,servings,calories,fat,sodium,0);
}
public NutritionFacts(int servingSize,int servings,int calories,int fat,int sodium,int carbohydrate){
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
}
}

当我们想要穿件实例的时候,就利用参数列表最短的构造器,但是该列表包含了要设置的所有参数:

NutritionFacts cocaCloa = new NutritionFacts(240,8,100,0,35,27);

这个构造器通常需要许多你本不想设置的参数,但是不能不为它传递值。在这个例子中,我们给fat传递了一个值为0。如果“仅仅”只有6个参数,看起来并不算太早,问题是随着参数数目的增加,它很快就会失去控制。

使用JavaBean模式,也能够代替这种问题。遗憾的是在一定的情况下,我们需要额外的努力来保证它的安全性。

幸运的是,还有新的替代方法,既能够保证向重叠构造器模式那样安全,也能够保证像JavaBean模式的那么好的可读性。这就是Builder模式的一种形式。不直接生成想要的对象。然后客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setting的方法,来设置每个相关的可选参数。最后,客户端调用午餐的build方法来生成不可变的对象。这个builder是他构建的类的静态成员类。

//Builder Pattern
public class NutritionFacts{
private final int servingSize; //required
private final int servings; //required
private final int calories; //optional
private final int fat; //optional
private final int sodium; //optional
private final int carbohydrate; //optional public static class Builder{
private final int servingSize; //required
private final int servings; //required
private int calories; //optional
private int fat; //optional
private int sodium; //optional
private int carbohydrate; //optional public Builder(int servingSize,int servings){
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val){
this.calories = val;
return this;
}
public Builder fat(int val){
this.fat = val;
return this;
}
public Builder sodium(int val){
this.sodium = val;
return this;
}
public Builder carbohydrate(int val){
this.carbohydrate = val;
return this;
}
public NutritionFacts build(){
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder){
this.servingSize = builder.servingSize;
this.servings = builder.servings;
this.calories = builder.calories;
this.fat = builder.fat;
this.sodium = builder.sodium;
this.carbohydrate = builder.carbohydrate;
}
}

注意NutrtionFacts是不可变的,所有的默认参数都是单独放在一个地方。builder的setter方法返回builder本身,以便可以把调用连接起来。

NutritionFacts nutritionFacts =
new NutritionFacts.Builder(240, 8)
.calories(100)
.sodium(35)
.carbohydrate(27)
.build();

这样的调用客户端代码很容易编写,更为重要的是易于阅读。

build方法可以检验这些约束条件。将参数从builder拷贝到对象中之后,并在对象域而不是builder域中对他们进行检验。如果违反了约束条件,build方法就应该抛出IllegalStateException。

Builder 模式自身的不足。为了创建对象,必须先创建它的构造器。虽然创建构造器的开销在实践中可能并不明显,但是在某些十分注重性能的情况下,可能就成问题了。

Builder 模式还比重叠构造器模式更加冗长,因此它只能在有很多参数的时候才使用。比如4个或者更多的参数。但是记住,将来你可能添加参数。如果一开始就是用构造器或者静态工厂,等类需要更多的参数时才添加构造器就会无法控制,那些过时的构造器或者静态工厂显得十分的不协调。因此,通常最好一开始就是用构造器。

简而言之,如果类的构造器或者静态工厂中具有多个参数,设计这种类的时,Builder模式就是种不错的选择,特别是当大多数的参数都是可选的时候。

builder模式的新学习的更多相关文章

  1. Android 开发学习进程0.30 builder模式创建popwindow

    builder模式创建自定义popwindow builder设计模式 将一个复杂的对象构建与它的表示分离,简化代码的使用方式.当对象有多个参数或多个零件同时初始化方法同时初始化方法有默认值时,采用此 ...

  2. 设计模式-----Builder模式

    前言 近日,看到Myabtis中组件中SqlSessionFactory由SqlSessionFactoryBuilder().build()生成时,且采用Builder模式,遂记录学习之. SqlS ...

  3. Java Builder 模式,你搞懂了么?

    加油.png 前言:最近闲来无事的时候想着看看一些平常用的三方库源码,没想到看了之后才知道直接撸源码好伤身体,一般设计优秀的开源库都会涉及很多的设计模式,就比如 android 开发使用频繁的 okH ...

  4. Java Builder 模式,你搞明白了么?

    Builder 模式定义 Builder 模式中文叫作建造者模式,又叫生成器模式,它属于对象创建型模式,是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.建造者模式是一步一步 ...

  5. Builder模式在Java中的应用

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

  6. 创建型模式之Builder模式及实现

    建造者(Builder)模式 GOF给出的定义为:建造者模式是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 应用场景 使用建造者模式是为了将构建复杂对象的过程和它的部件 ...

  7. Android Builder模式在开发中的应用

    最近在学习图片加载框架Glide的时候,被他精简的写法震惊了.一句话,就可以搞定. Glide.with(mContext) .load(url) .centerCrop() .placeholder ...

  8. Builder模式(建造者模式)

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

  9. Builder模式在Java中的应用(转)

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

随机推荐

  1. ElasticSearch(九)基于version进行乐观锁并发控制

    一.基于version进行乐观锁并发控制 1).查看一条document GET /test_version/test_version_type/ { "_index" : &qu ...

  2. 远程请求json数据,list中显示

    public class MainActivity extends Activity { protected static final int WHAT_REQUEST_SUCCESS = 1; pr ...

  3. c++中class与struct的区别

    0. 结构是一种用关键字struct声明的自定义数据类型.与类相似,也可以包含构造函数,常数,字段,方法,属性,索引器,运算符和嵌套类型. 1.结构在堆栈中创建,是值类型,而类是引用类型.每当需要一种 ...

  4. [usaco2009nov]奶牛的图片

    Farmer John希望给他的N(1<=N<=100,000)只奶牛拍照片,这样他就可以向他的朋友炫耀他的奶牛.这N只奶牛被标号为1..N.在照相的那一天,奶牛们排成了一排.其中第i个位 ...

  5. UVALive - 4867 —— dp

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  6. haproxy官方配置文档地址

    http://cbonte.github.io/haproxy-dconv/1.6/configuration.html#4-option%20http-keep-alive

  7. codeforces 465C.No to Palindromes! 解题报告

    题目链接:http://codeforces.com/problemset/problem/464/A 题目意思:给出一个长度为 n 且是 tolerable 的字符串s,需要求出字典序最小的长度也为 ...

  8. ubuntu下安装cpython 0.2x

    Quick installation of cython: Step 1: Update system: sudo apt-get update Step 2: Install: cython Ate ...

  9. ubuntu166.04之Caffe安装

    写在前面:之前一直在搞keras,最近由于某些需求,需要学习caffe,在此记录caffe的安装记录.默认已经安装了cuda 如果是从其他的深度学习平台迁移到Caffe,那么按照这个教程来就可以了. ...

  10. 【CQ18高一暑假前挑战赛3.5】标程

    [A:快速幂相关] #include<bits/stdc++.h> using namespace std; int qpow(int a,int x){ a%=;; while(x){ ...