定义:建造者模式又叫生成器模式,是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
话不多说,上本次实现代码类图:
令人头大,那么我们就一步一步来解读QAQ
移动设备模型的抽象类
public abstract class MobilleModel {
private ArrayList<String> sequence = new ArrayList<String>();
//获取基础组件
protected abstract void getElement();
//获取电话功能组件
protected abstract void getCall();
//获取音乐功能组件
protected abstract void getMusic();
//获取视频功能组件
protected abstract void getVideo();
//获取外壳,装好了
protected abstract void getShell();
//组装
final public void packaging(){
//循环,谁在前先执行谁
for (String str : this.sequence){
if(str.equals("element")){
this.getElement();
}else if(str.equals("call")){
this.getCall();
}else if(str.equals("music")){
this.getMusic();
}else if(str.equals("video")){
this.getVideo();
}else if(str.equals("shell")){
this.getShell();
}
}
}
//把传递过来的值传递到类内
final public void setSequence(ArrayList<String> sequence){
this.sequence = sequence;
}
}
MobilleModel 设计原理是这样的,setSequence 方法是自己设置一个顺序,确定组装顺序。对于一个具体的模型永远都是固定的,但是对N个模型就是动态的。在子类实现父类的基本方法,packaging 方法读取sequence ,然后遍历sequence 中的字符串,哪个字符串在先,就先执行哪个方法。
手机模型代码
public class PhoneModel extends MobilleModel {
protected void getElement() {
System.out.println("组装手机基础组件,处理器等等");
}
protected void getCall() {
System.out.println("组装手机通话组件,可以打电话");
}
protected void getMusic() {
System.out.println("组装手机音乐组件,可以放音乐");
}
protected void getVideo() {
System.out.println("组装手机视频组件,可以播视频");
}
protected void getShell() {
System.out.println("组装手机外壳,组装好了,出厂");
}
}
平板模型代码
public class PadModel extends MobilleModel {
protected void getElement() {
System.out.println("组装Pad基础组件,处理器等");
}
protected void getCall() {
System.out.println("组装Pad通话组件,可以通话");
}
protected void getMusic() {
System.out.println("组装Pad音乐组件,可以通话");
}
protected void getVideo() {
System.out.println("组装Pad视频组件,可以视频");
}
protected void getShell() {
System.out.println("组装Pad外壳,组装好,出厂");
}
}
两个产品的实现类都完成,我们来模拟一下:组装一部手机以及一部平板。显然很容易实现:
public class BuilderTest {
public static void main(String[] args) {
//存放执行顺序
ArrayList<String> sequence = new ArrayList<String>();
sequence.add("element");
sequence.add("call");
sequence.add("music");
sequence.add("video");
sequence.add("shell");
//组装出一部手机
PhoneModel phoneModel = new PhoneModel();
phoneModel.setSequence(sequence);
phoneModel.packaging();
//按照同样的顺序,组装一个pad
PadModel padModel = new PadModel();
padModel.setSequence(sequence);
padModel.packaging();
}
}
运行结果如下:
组装手机基础组件,处理器等等
组装手机通话组件,可以打电话
组装手机音乐组件,可以放音乐
组装手机视频组件,可以播视频
组装手机外壳,组装好了,出厂
组装Pad基础组件,处理器等
组装Pad通话组件,可以通话
组装Pad音乐组件,可以通话
组装Pad视频组件,可以视频
组装Pad外壳,组装好,出厂
这样,我们就组装出来一部手机以及一部平板。但,试想,这样只能满足一种手机和平板的组装,如果还想有另外的呢,难道无休无止地创建模型?显然不好!那么我们就为每种模型产品定义一个建造者,要什么组装顺序直接告诉建造者,由建造者来建造。
增加一个抽象类,由它来组装各个模型,要什么顺序的模型,都由相关的子类完成。
public abstract class MobileBuilder {
//创建模型,给组装顺序
public abstract void setSequence(ArrayList<String> sequence);
//设置完组装顺序后,直接可以拿到组装生产线
public abstract MobilleModel getMobilleModel();
}
public class PhoneBuilder extends MobileBuilder {
private PhoneModel phoneModel = new PhoneModel();
public void setSequence(ArrayList<String> sequence) {
this.phoneModel.setSequence(sequence);
}
public MobilleModel getMobilleModel() {
return this.phoneModel;
}
}
public class PadBuilder extends MobileBuilder{
private PadModel padModel = new PadModel();
public void setSequence(ArrayList<String> sequence) {
this.padModel.setSequence(sequence);
}
public MobilleModel getMobilleModel() {
return this.padModel;
}
}
两个组装线都完成了,修改一下场景类,再生产两部设备
public class BuilderTest {
public static void main(String[] args) {
//存放执行顺序
ArrayList<String> sequence = new ArrayList<String>();
sequence.add("element");
sequence.add("call");
sequence.add("music");
sequence.add("video");
sequence.add("shell");
//要一部手机
PhoneBuilder phoneBuilder = new PhoneBuilder();
//把顺序给这个builerd类,组装出这样一部手机出来
phoneBuilder.setSequence(sequence);
PhoneModel phone = (PhoneModel) phoneBuilder.getMobilleModel();
//组装出一部手机
phone.packaging();
//按照同样的顺序,组装一个pad
PadBuilder padBuilder = new PadBuilder();
padBuilder.setSequence(sequence);
PadModel pad = (PadModel) padBuilder.getMobilleModel();
pad.packaging();
}
}
运行结果:
组装手机基础组件,处理器等等
组装手机通话组件,可以打电话
组装手机音乐组件,可以放音乐
组装手机视频组件,可以播视频
组装手机外壳,组装好了,出厂
组装Pad基础组件,处理器等
组装Pad通话组件,可以通话
组装Pad音乐组件,可以通话
组装Pad视频组件,可以视频
组装Pad外壳,组装好,出厂
看,同样组装顺序的移动设备都生产出来了,而且代码比刚开始直接访问产品类简单了许多。那如果还想有其他组装顺序的设备呢,并且不知道具体的顺序,可以随意指定,怎么办?封装一下,找个导演,指挥:
public class Director {
private ArrayList<String> sequence = new ArrayList<String>();
private PhoneBuilder phoneBuilder = new PhoneBuilder();
private PadBuilder padBuilder = new PadBuilder();
//功能机
public PhoneModel getNotSmartPhone(){
this.sequence.clear();
sequence.add("element");
sequence.add("call");
sequence.add("shell");
this.phoneBuilder.setSequence(sequence);
return (PhoneModel) this.phoneBuilder.getMobilleModel();
}
//智能机
public PhoneModel getSmartPhone(){
this.sequence.clear();
sequence.add("element");
sequence.add("call");
sequence.add("music");
sequence.add("video");
sequence.add("shell");
this.phoneBuilder.setSequence(sequence);
return (PhoneModel) this.phoneBuilder.getMobilleModel();
}
//可以插卡通话的pad
public PadModel getCallPad(){
this.sequence.clear();
sequence.add("element");
sequence.add("call");
sequence.add("music");
sequence.add("video");
sequence.add("shell");
this.padBuilder.setSequence(sequence);
return (PadModel) this.padBuilder.getMobilleModel();
}
//无通话功能的pad
public PadModel getNOTCallPad(){
this.sequence.clear();
sequence.add("element");
sequence.add("music");
sequence.add("video");
sequence.add("shell");
this.padBuilder.setSequence(sequence);
return (PadModel) this.padBuilder.getMobilleModel();
}
}
有了这么一个导演类之后,需求就更容易处理了,比如要1个智能机,两个功能机,3个可通话pad,4个无通话功能pad:
public class BuilderTest {
public static void main(String[] args) {
Director director = new Director();
for (int i = 0; i < 1; i++) {
director.getSmartPhone().packaging();
}
for (int i = 0; i < 2; i++) {
director.getNotSmartPhone().packaging();
}
for (int i = 0; i < 3; i++) {
director.getCallPad().packaging();
}
for (int i = 0; i < 4; i++) {
director.getNOTCallPad().packaging();
}
}
}
最后的代码就是这般清晰而简单。
总结
优点:
1、封装性
2、建造者独立,容易扩展
3、便于控制细节风险
经典使用场景
相同的方法,不同的执行顺序,产生不同的结果