前言(微剧场):
小架昨天跟女朋友吵架了(什么?这个弟弟竟然有女朋友?先别急,别急,就假装一下他有,毕竟我们故事还要讲下去对不?),咳..于是呢,小架今天拿着女朋友昨天给的钱打算去电脑城去配一台新的电脑。
这咋又扯到女朋友吵架咧?这...不会又是想水文章吧,别慌嘛,事情的经过是这样滴...
话说昨日窗外阴风阵阵,雷雨交加,小架此刻正在英雄联盟召唤师大峡谷中提着40米大刀进行着激烈厮杀,殊不知,有一双眼睛悄悄出现在他的身后。小架感觉到自己后背一阵凉意,紧忙往后一看,转身后发现有人站在身后,正要发怒,千钧一发之际,看到竟是小架的女友,瞬间认怂。这个,姑奶奶,你听我解释,你听我解释,我就玩了一把。女友气势汹汹,说你多少次了,天天玩游戏,天天玩游戏,除了玩游戏你还能干点啥!嗯?
小架想自己此刻必然在劫难逃,这样下去怕是要鱼死网不破,看到自己破旧的电脑,新生妙计,急忙从桌子上拿起使出吃奶的力气将电脑摔个稀烂,摆出悲痛欲绝状,犹如绝别的情侣却要忍痛割爱般大喊: 不玩了,不玩了就是!
小架的女友没想到自己无意的一句嘟哝,竟然让他做出如此过激的举动,看着地上被摔得稀巴烂的小架钟爱的电脑,心中不免心生愧疚,只得连忙安慰道:
也不是不让你玩,这样,我给你点钱你再去买个新的电脑吧,还要工作呢,记得下次可别这么玩游戏了。小架摆出一脸委屈,内心疯狂窃喜,接过钱去头也不回的迈着欢快的步伐向电脑城扭秧歌般跑去。
来到电脑城,小架告诉了老板自己想要的配置,不到两个小时,一台崭新的地球人顶配笔记本已经交付到了小架手中。
这么一看这不就是工厂模式吗?有啥好讲的,取关。 别别别,真不是在水文章啊,您往下看我们先来讲一下建造者模式吧
建造者模式定义:
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
优/缺点:
优点:
建造者独立,易扩展。
便于控制细节风险。
缺点:
产品必须有共同点,范围有限制。
如内部变化复杂,会有很多的建造类.
应用场景:
需要生成的对象具有复杂的内部结构。
建造者模工按流程一步步地创建出复杂对象.
用户不知道对象的建造过程和细节就可以创建出复杂的对象「屏蔽了建造的具体细节」
需要生成的对象内部属性本身相互依赖。
应用案例:
JAVA中的StringBuilder对象
安卓开发中的 AlertDialog对象
.....略。 别取关呀~
且慢,我们先看代码:
且慢,看代码之前先看建造者模式之间的角色分工:
角色分工:
Builder 抽象的建造者,一般是接口或者抽象类。
ConcreateBuilder 具体的建造者。
Product 产品类。
Director 指挥者。指挥建造者去建造目标。
其中 Builder 和Director 都不是必须的,部分场景下可以省略。
代码实战:
首先,我们先新建我们的产品类:Computer
public class Computer {
private String cpu ; // cpu
private String hardDisk ; //硬盘
private String mainBoard ; // 主板
private String memory ; // 内存
private String keyboard;//键盘
private String mouse;//鼠标
/*
getter and setter and toString
*/
}
声明Builder ,规范了安装电脑的步骤,至于你安装什么样的显卡,这个并不是建造者会关心的,建造者只关心对象的组装。
public class ComputerBuilder implements Builder{
private Computer computer = new Computer() ;
@Override
public void installMainBoard(String mainBoard) {
computer.setMainBoard(mainBoard);
}
@Override
public void installCpu(String cpu) {
computer.setCpu(cpu);
}
@Override
public void installhardDisk(String hardDisk) {
computer.setHardDisk(hardDisk);
}
@Override
public void installMemory(String memory) {
computer.setMemory(memory);
}
@Override
public void installKeyBoard(String keyboard) {
computer.setKeyboard(keyboard);
}
@Override
public void installMouse(String mouse) {
computer.setMouse(mouse);
}
@Override
public Computer createComputer() {
return computer;
}
}
声明我们的指挥者类,我们的地球人电脑实际上就是在这里按照一定顺序装配完成的,而ComputerBuilder负责完成具体的装配工作。
public class Director {
private Builder builder ;
public Director(Builder builder){
this.builder = builder ;
}
public Computer createComputer(String cpu,String hardDisk,String mainBoard,String memory,String keyboard,String mouse){
this.builder.installMainBoard(mainBoard);
this.builder.installCpu(cpu) ;
this.builder.installMemory(memory);
this.builder.installhardDisk(hardDisk);
this.builder.installKeyBoard(keyboard);
this.builder.installMouse(mouse);
return this.builder.createComputer() ;
}
}
测试类:
public class Test {
public static void main(String[] args) {
Builder builder = new ComputerBuilder();
Director director = new Director(builder);
Computer computer = director.createComputer("I9", "三星", "华硕", "三星" ,"罗技", "罗技");
System.out.println(computer);
}
}
```
输出:
Computer [cpu=I9, hardDisk=三星, mainBoard=华硕, memory=三星, keyboard=罗技, mouse=罗技]
我们来看一下建造者模式一个具体的执行流程:
小架提出自己的需求,如要什么主板..
指挥者收到需求,并把需求转交给建造者(Builder)
建造者收到需求装配对象,然后返回给指挥者
指挥者把装好的地球人顶配电脑转交给小架
这么一看确实是和工厂模式没什么不一样的,注意了,如果我们小架挑选电脑配置这个行为是随机的,即处理器任何一款都可以,同理硬盘,内存也是,这样下来就会有几乎无数种组合了,而值得我们所有人注意的是,工厂模式中所创建的对象是固定的,即不管你调用多少次这个工厂,造出来的对象都一个鸟样。这意味这,面对这种情况我们就需要有无数个工厂对应不同的电脑配置组合,而这一切在我们建造者模式面前都是弟弟。
随便提需求,我传进去,建造者模式组装就OK了。而且我不仅可以造电脑,比如我不想买你家的键盘,我可以给个null,做到对细节的控制,同时建造者和工厂模式相同的是,建造者相对于产品是独立的,即我可以很方便的增加新的建造者,而不对其他的建造者产生影响,到这里,我们开头的优点
-建造者独立,易扩展。
-便于控制细节风险。
当然,建造者模式和工厂模式之间的较量才刚刚开始,至于它们两个具体不同在哪?且看下面分解
建造者模式VS工厂模式:
相同点:
都属于创建型设计模式注:在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。
不同点:
创建对象的细粒度不同工厂模式比较粗放,造出来都是一个鸟样,而建造者模式不一样了,你甚至可以决定很多产品的细节。
应用场景不同,关注点不一样工厂模式关注的是这个对象,客户端无需知道这个对象的细节,只管找相应的工厂要装好的就行了。而建造者模式则关注对象创建的细节,客户端知道一部分产品组成的细节,比如上例中电脑显卡型号,硬盘型号等。
建造者模式一般用来创建比较复杂的对象,工厂模式则用于创建相对来说比较简单的对象。
等等,不对,我记得我见到过的建造者模式不是这样的,明明就是那种,你看
AlertDialog.Builder builder = new AlertDialog.Builder(this);
这里并没有出现什么指挥者角色啊,难道这个不是建造者模式吗?可上面你明明说是的啊。
根据我们之前的经验,实际开发中并不一定总是采用设计模式的标准实现,建造者模式也是如此,既然上文建造者模式角色那一小节有说Builder和Director并不是必须的,那必然有一种建造者模式的实现是省略了这些的,答案是有的,实际上呢,在要求不是那么严格的情况下,建造者模式有更为简洁的写法,这里我将它称之为:
建造者模式极速版!(请读者自行脑补哆啦A梦配音)
建造者模式(极速版):
代码如下:
package code.builder.fast;
public class Computer {
private String cpu ; // cpu
private String hardDisk ; //硬盘
private String mainBoard ; // 主板
private String memory ; // 内存
private String keyboard;//键盘
private String mouse;//鼠标
//定义成private,使其不能被直接创建出来
private Computer() {}
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getHardDisk() {
return hardDisk;
}
public void setHardDisk(String hardDisk) {
this.hardDisk = hardDisk;
}
public String getMainBoard() {
return mainBoard;
}
public void setMainBoard(String mainBoard) {
this.mainBoard = mainBoard;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getKeyboard() {
return keyboard;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public String getMouse() {
return mouse;
}
public void setMouse(String mouse) {
this.mouse = mouse;
}
@Override
public String toString() {
return "Computer [cpu=" + cpu + ", hardDisk=" + hardDisk + ", mainBoard=" + mainBoard + ", memory=" + memory
+ ", keyboard=" + keyboard + ", mouse=" + mouse + "]";
}
//Builder 静态内部类
public static class ComputerBuilder {
//创建computer实例
private Computer computer = new Computer();
//必须的参数
public ComputerBuilder(String cpu,String hardDisk,String mainBoard,String memory) {
computer.setCpu(cpu);
computer.setHardDisk(hardDisk);
computer.setMainBoard(mainBoard);
computer.setMemory(memory);
}
//以下是额外可附加的配置
public ComputerBuilder bulidKeyBoard(String keyboard) {
computer.setKeyboard(keyboard);
return this;
}
public ComputerBuilder buildMouse(String mouse) {
computer.setMouse(mouse);
return this;
}
//对象返回
public Computer create() {
if (computer==null){
throw new IllegalStateException("computer is null");
}
return computer;
}
}
}
测试:
public class Test {
public static void main(String[] args) {
Computer computer = new Computer.ComputerBuilder("i9", "三星", "华硕", "金士顿")
.buildMouse("罗技")
.bulidKeyBoard("雷蛇")
.create();
System.out.println(computer);
}
}
输出:
Computer [cpu=i9, hardDisk=三星, mainBoard=华硕, memory=金士顿, keyboard=雷蛇, mouse=罗技]
当然,和工厂模式,单例模式一样,上述建造者模式极速版也只是其中的一种写法,设计模式并没有标准的写法,但是万变不离其宗,其所体现出来的思想往往是相同的,所以小伙伴们如果见到有不同写法的建造者模式也不必惊讶,最终还是要符合建造者模式定义的。
把握住变化中不变的那一部分,等于把握住了全部
总结:
本篇文章较为详细的阐述了建造者模式的思想以及具体的代码实现,建造者模式虽然不是大量使用的设计模式,但是也往往很容易就见到它的身影,掌握之后不管是对于开发还是阅读源码都会有所帮助,同样的,用大量废话尽量帮助看到这篇文章的朋友搞清楚建造者模式和工厂模式之间的差别,也希望各位看完了能觉得有用,虽然废话有点多哈哈哈。
我是小架,我们下篇文章再见!