建造者模式
建造者模式是在Android中很常见的一种设计模式,比如系统自带的AlertDialog就是以建造者模式供我们使用的,如下:
AlertDialog dialog = new AlertDialog.Builder(context) .setIcon(R.drawable.icon) .setTitle("title") .setMessage("message") .setPositiveButton("positive", (dialog1, which) -> { }).setNegativeButton("negative", (dialog12, which) -> { }) .create(); dialog.show();
对于AlertDialog这个复杂的对象,使用建造者模式可以让对象创建的过程分步进行,传参清晰明了,选择性的传入需要的参数来创建所需的对象,而不必关心内部的实现过程,也不必像构造普通对象那样必须在构造方法中传入所有参数,或者有太多的set()方法,不知道调用哪个。
以上的建造者写法实际上是一个简化版,标准的建造者模式应有以下几种角色:
1.Product——抽象产品类;
2.Builder——抽象建造者类,定义基本的建造方法,对于不同的产品,需要继承建造者类,实现具体的建造方法;
3.Director——规范抽象建造者的建造过程。
以组装电脑为例,假设组装电脑至少需要CPU、GPU、内存和系统,定义抽象电脑类:
public abstract class BaseComputer { protected String cpu; protected String gpu; protected int ram; protected String os; protected BaseComputer() { } public void setCpu(String cpu) { this.cpu = cpu; } public void setGpu(String gpu) { this.gpu = gpu; } public void setRam(int ram) { this.ram = ram; } public abstract void setOS(String os); @Override public String toString() { return "Computer:" + " cpu: " + cpu + " gpu: " + gpu + " ram: " + ram; } }
定义抽象建造者类:
public abstract class BaseComputerBuilder { public abstract void ofCpu(String cpu); public abstract void ofGpu(String gpu); public abstract void ofRam(int ram); public abstract void ofOS(); public abstract BaseComputer create(); }
实现抽象电脑类:
public class Mac extends BaseComputer { @Override public void setOS() { os = "Mac OS"; } }
实现抽象建造者类:
public class MacBuilder extends BaseComputerBuilder { private Mac mac = new Mac(); @Override public void ofCpu(String cpu) { mac.setCpu(cpu); } @Override public void ofGpu(String gpu) { mac.setGpu(gpu); } @Override public void ofRam(int ram) { mac.setRam(ram); } @Override public void ofOS() { mac.setOS(); } @Override public BaseComputer create() { return mac; } }
最后用Director角色来规范建造方法的调用:
public class Director { private BaseComputerBuilder builder; public Director(BaseComputerBuilder builder) { this.builder = builder; } public void construct(String cpu, String gpu, int ram) {
//对象的建造过程 builder.ofCpu(cpu); builder.ofGpu(gpu); builder.ofRam(ram); builder.ofOS(); } }
使用时需要创建建造者和Director对象,传入相应的参数,而不需要关心建造的过程:
public static void main(String[] args) { BaseComputerBuilder builder = new MacBuilder(); Director director = new Director(builder); director.construct("cpu", "gpu", 8); System.out.println("Computer: " + builder.create().toString()); }
类似于系统的AlertDialog对象,我们常常为了简化结构而去掉Director角色,在Builder的建造方法中返回自己,通过链式调用的形式组装对象。修改抽象建造者和具体实现:
public abstract class BaseComputerBuilder { public abstract BaseComputerBuilder ofCpu(String cpu); public abstract BaseComputerBuilder ofGpu(String gpu); public abstract BaseComputerBuilder ofRam(int ram); public abstract BaseComputerBuilder ofOS(); public abstract BaseComputer create(); }
public class MacBuilder extends BaseComputerBuilder { private Mac mac = new Mac(); @Override public BaseComputerBuilder ofCpu(String cpu) { mac.setCpu(cpu); return this; } @Override public BaseComputerBuilder ofGpu(String gpu) { mac.setGpu(gpu); return this; } @Override public BaseComputerBuilder ofRam(int ram) { mac.setRam(ram); return this; } @Override public BaseComputerBuilder ofOS() { mac.setOS(); return this; } @Override public BaseComputer create() { return mac; } }
使用时更加简洁,这适用于建造方法较少或过程简单,不需要统一管理的情况:
new MacBuilder().ofCpu("cpu") .ofGpu("gpu") .ofRam(8) .ofOS() .create();
以上的建造者模式写法在大多数情况下已经够用了,但是为了对所有同类的产品的建造进行约束,限制只能用规定的建造方法来获取对象,我们可以将抽象建造者写在抽象产品内部,作为产品的内部类,并使用范型来约束建造方法的返回值:
public abstract class BaseComputer { protected String cpu; protected String gpu; protected int ram; protected BaseComputer(BaseComputerBuilder builder) { this.cpu = builder.cpu; this.gpu = builder.gpu; this.ram = builder.ram; } @NonNull @Override public String toString() { return "Computer:" + " cpu: " + cpu + " gpu: " + gpu + " ram: " + ram; } public abstract static class BaseComputerBuilder<T extends BaseComputerBuilder<T, K>, K extends BaseComputer> { private String cpu = "default cpu"; private String gpu = "default gpu"; private int ram = 1; public T ofCpu(String cpu) { this.cpu = cpu; return (T)this; } public T ofGpu(String gpu) { this.gpu = gpu; return (T)this; } public T ofRam(int ram) { this.ram = ram; return (T)this; } public abstract K build(); } }
这样同类型的产品在继承时,就可以有同类型的建造者,并且可以根据不同产品的需要,扩展更多的字段和建造方法,而又具备基本的建造方法:
public class AppleMac extends BaseComputer { //扩展的字段 private String os; private AppleMac(AppleMacBuilder builder) { super(builder); this.os = builder.os; } public String getOS() { return os; } public static class AppleMacBuilder extends BaseComputerBuilder<AppleMacBuilder, AppleMac> { private String os = "default system"; public AppleMacBuilder ofOS(String os) { this.os = os; return this; } @Override public AppleMac build() { return new AppleMac(this); } } }
另外,我们在建造者中给字段设置了默认值,所以在创建时可以只传入需要自定义的字段:
public static void main(String[] args) { AppleMac appleMac = new AppleMac.AppleMacBuilder() .ofCpu("cpu") .ofOS("Mac OS") .build(); System.out.println(appleMac.toString()); }
综上,建造者模式很好的封装了复杂对象的创建过程,避免有太多的set()方法。对象创建时可以根据不同的传参和调用顺序产生不同的结果,对象的创建过程得到了统一管理,接口更加清晰,简洁易懂。并且抽象的建造者对于不同的产品建造也有更好的可扩展性。至于Director角色,如果建造过程不固定,不同产品有不同的实现,可以省略这个角色,直接在建造者中管理各自的建造过程。

浙公网安备 33010602011771号