序言
在看Retrofit源码时,可以看到里面用到了大量的设计模式,如果我们非常了解设计模式对理解是很有帮助的,在Rerofit里有用到建造者模式。
建造者模式定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以生成不同的表示。建造者模式也是对象创建行模式。
说明:单看这个定义初学者也是很蒙, 大概意思是不需要关心复杂对象创建过程,只需要知道建造者类型即可,建造者才关心这个复杂对象是如何一步一步创建一个复杂对象的。根据不同类型的建造者生成不同的复杂的对象。也是有具有良好的扩展性。
建造者模式类图

建造者模式类图
在建造者模式中包含如下几个角色:
-
Builder(抽象的建造者) : 它是创建Product对象各个部分的抽象接口。在该接口一般有两类接口 ,一种是biuldPartX()方法,用于创建该复杂对象各个部分;另一种方法是getResult, 它用于返回这个复杂对象。Build可以是一个接口,也可以是抽象类。
-
ConcreteBuilder(具体的建造者):它实现了Builder接口,具体实现该复杂对象的各个部分,然后返回具体的复杂对象。
-
Product(产品角色): 它是复杂对象,里面包含该对象有哪些部分组成。
-
Director(指挥者):它负责对象的建造次序。指挥者和抽象的建造者存在关联关系,可以在construct中完成复杂对象的创建过程。
上面有提到复杂对象,那什么是复杂对象呢,简单来说就是包含多个成员属性的对象。代码示例如下:
//产品class Product{ private String partA;//定义产品的属性,属性可以是其它类型, 值类型和引用类型都行。 private String partB; private String partC; //Setter和Getter方法省略就不写了}
在抽象建造者定义产品的创建方法和获取产品对象的方法。代码示例如下:
//抽象建造者interface Builder{ void buildPartA();//创建产品的属性 void buildPartB(); void buildPartC(); Product getResult(); //返回产品对象}
抽象建造者中申明了一系列的buildPartX()方法,但是具体的实现还是需要具体的建造者。不同的建造者实现的buildPartX有所区别。代码示例如下:
//具体的建造者 Apublic class AConcreteBuilder implements Builder {Product productA=new Product();@Overridepublic void buildPartA() { productA.setPartA("PartA from AConcreteBuilder");}@Overridepublic void buildPartB() { productA.setPartA("PartB from AConcreteBuilder");}@Overridepublic void buildPartC() { productA.setPartA("PartC from AConcreteBuilder");}@Overridepublic Product getResult() { return productA;}}//具体的建造者 Bpublic class BConcreteBuilder implements Build {Product productB=new Product();@Overridepublic void buildPartA() { productB.setPartA("PartA from BConcreteBuilder");}@Overridepublic void buildPartB() { productB.setPartA("PartB from BConcreteBuilder");}@Overridepublic void buildPartC() { productB.setPartA("PartC from BConcreteBuilder");}@Overridepublic Product getResult() { return productB;}}
我们可以看到每个建造者实现的东西是不同的。但是返回的产品还是一类的,只是产品的属性不一样。
在建造者模式还有个Director角色(导演者或指挥者),该类主要有两个作用:其一就是控制产品的创建过程,包括biuldPartX方法是否被调用以及调用的顺序; 其二 就是隔离了客户与创建的过程, Director只需要指挥抽象的建造者(Build),客户端需要具体的建造者然后调用指挥者的相关方法,返回一个完整的对象(Product)。代码示例如下
//指挥者public class Director {private Builder mBuilder; //抽象的建造者public Director(Builder build) { this.mBuilder = build;}public Product construct(){ mBuilder.buildPartA(); mBuilder.buildPartB(); mBuilder.buildPartC(); return mBuilder.getResult();}}//客户端 代码片段如下Builder Abuilder=new AConcreteBuilder();//创建具体的建造者Director director=new Director(Abuilder);//创建指挥者Product productA=director.construct();//返回产品ABuilder Bbuilder=new BConcreteBuilder();//创建具体的建造者Director director=new Director(Bbuilder);//创建指挥者Product productA=director.construct();//返回产品B
建造者模式例子
如某个公司要开发个APP(Product),就需要开发者(Builder), 如果有多端的话就需要不同的开发者(ConcreteBuilder),技术经理(Director)就充当指挥者来指示不同的开发者来开发。
APP (Product)
public class APP { String code;//代码 String note;//注释及文档 public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } @Override public String toString() { return "APP = {" + "code="" + code + "\"" + ", note="" + note + "\"" + "}"; }}
开发者 (Builder)
public interface Developer { void writeCode();//写代码 void writeNote();//写文档及注释 APP getAPP();//返回APP}
Andoird开发者(ConcreteBuilder)
public class AndroidDeveloper implements Developer { APP app = new APP(); @Override public void writeCode() { app.setCode("Android code"); } @Override public void writeNote() { app.setNote("Android note "); } @Override public APP getAPP() { return app; }}
技术经理 (指挥者)
public class TechnicalManager { Developer mDeveloper; public void setDeveloper(Developer mDeveloper) { this.mDeveloper = mDeveloper; } public APP getAPP() { mDeveloper.writeCode(); mDeveloper.writeNote(); return mDeveloper.getAPP(); }}
测试:
public static void main(String[] args) { TechnicalManager manager = new TechnicalManager();//创建技术经理对象(指挥者) AndroidDeveloper javaDeveloper = new AndroidDeveloper();//创建Android开发者(具体的建造者) manager.setDeveloper(javaDeveloper);//技术经理指挥Android程序员去干活 APP app = manager.getAPP(); //完成 Android端 APP System.out.println(app); }
运行结果:
APP = {code="Android code", note="Android note"}
如果公司想在苹果商店也要上款APP,那就需要ios开发,这样我们就不用修改源代码,只需要另创建一个ios的建造者就OK。
ios 开发者(ConcreteBuilder)
public class IosDeveloper implements Developer { APP app = new APP(); @Override public void writeCode() { app.setCode("ios code"); } @Override public void writeNote() { app.setNote("ios note"); } @Override public APP getAPP() { return app; }}
测试:
public static void main(String[] args) { TechnicalManager manager = new TechnicalManager();//创建技术经理对象(指挥者) IosDeveloper iosDeveloper = new IosDeveloper();//创建ios开发者(具体的建造者) manager.setDeveloper(iosDeveloper);//技术经理指挥ios程序员去干活 APP app = manager.getAPP(); //完成 ios端 APP System.out.println(app);}
运行结果:
APP {code="ios code", note="ios note"}
如果需要其他端的APP,只需另创建个建造者就可以完成APP。
但是我们看大多数的源码,里面的建造者模式是没有指挥者的(Director),这个又是怎样实现的呢。 在Android中的弹框(dialog)的实现就用了建造者模式,我们就大致实现下它是怎么创建的。源码中还是很复杂的,这里只是简单实现。
在Android中创建一个dialog的代码
AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle("提示") .setMessage("消息") .setIcon(R.drawable.icon); AlertDialog alertDialog=builder.create();
这是Android创建dialog最简单的方式。 现在我们就实现这样的写法。
// Productpublic class AlertDialog{ String msg;//消息 String tilte;//标题 int icon; //图标 @Override public String toString() { return "AlertDialog{" + "msg="" + msg + "\"" + ", tilte="" + tilte + "\"" + ", icon=" + icon + "}";}//建造者 (Builder) static class Builder{ private AlertDialog mDialog=new AlertDialog(); public Builder setIcon(int icon){ mDialog.icon=icon; return this; } public Builder setTitle(String title){ mDialog.tilte=title; return this; } public Builder setMsg(String msg){ mDialog.msg=msg; return this; } public AlertDialog create(){ return mDialog; } }}
测试 :
public static void main(String args[]) { //因为Builder是AlertDialog的成员内部类,所以这样调用AlertDialog.Builder AlertDialog.Builder builder = new AlertDialog.Builder(); builder.setIcon(1) .setMsg("消息") .setTitle("提示"); AlertDialog dialog = builder.create(); System.out.println(dialog);}
运行结果:
AlertDialog{msg="消息", tilte="提示", icon=1}
可以看到我们也按照Android源码这样的调用方法创建了自己的dialog。Android中的dialog实现比我这复杂,dialog属性更多,逻辑更复杂。
我们可以再看看Retrofit中使用的建造者模式
Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build();
这是创建Retrofit对象。可以看到也是用了建造者模式。这里就不说了,下次分析源码时再说。
总结:建造者模式只要明白四个角色Product、Builder、ConcreteBuilder、Director的作用,就差不多明白建造者模式是怎么回事了。
优点:
-
将产品的本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
-
每一个具体建造者都是相对独立的,不依赖其他的具体建造者,可以方便地替换和增加新的具体建造者,用户使用不同的具体建造者就能得到不同的产品对象。由于指挥者(Director)是针对抽象的建造者(Builder)编程,增加新的建造者无需修改原来的建造者,符合‘开闭原则’。
缺点:
-
所创建的产品具有较多的共同点,其组成部分相似。如果产品之间的差异性很大的话,就不适用建造者模式。
-
产品的内部变化复杂的话,可能会导致定义很多的具体建造者来应对这样的变化,这样会导致系统的复杂性。
品略图书馆 http://www.pinlue.com/

本文深入解析建造者模式,阐述其定义、角色与实现方式,通过示例代码展示如何创建复杂对象,同时讨论模式的优点与局限性。
12万+

被折叠的 条评论
为什么被折叠?



