17. 建造者模式
2018-07-03 本文已影响10人
Next_吴思成
定义
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
通俗理解
有些同学组装过电脑💻,组装台式电脑的时候,需要考虑的东西有很多,CPU是用Intel的还是ARM的?显卡要中端的还是高端的?显示器要曲面屏的还是平面屏的?内存要多大?硬盘是用SSD还是HHD?这些都是要考虑的,然后我们会上网找各个型号的CPU,看他们的优点缺点价格,挑选完合适的CPU后,然后看显卡的资料... ...选好之后,装上通电,呵呵🙃,cpu用的是奔腾系列的,开不了机了。这个就是自己组装电脑的弊处,不了解硬件的信息,完全不知道要怎么搭配。
现在,有许多带逛电脑城的专业人士,只要支付他们一点费用,他们就会和我们一起逛电脑城。按照我们的需求,给我们挑选合适的配置,例如要愉快吃鸡,那么就需要i7的处理器,1080的显卡,而只是处理一般的文档,那就只需要i5的处理器,用集成显卡就可以了。不仅如此,忧郁他们是吃这一行的,和电脑城的老板熟络,他们还会帮忙砍价,让我们能够用更少的钱去组装自己的理想主机。
建造者模式就是这样的一种形式。当我们需要一个复杂的对象,不会选择自己处理,交给专业的人士进行建造,专业的人士会根据我们的需求,给我们提供各种方案,免去我们一个个拼凑的局面的出现。
示例
业务按组装电脑业务做演示。
渣渣程序
电脑
public class Computer {
private String cpu;
private String memory;
private String disk;
private String videoCard;
private String screen;
}
调用方
public class Main {
public static void main(String[] args) {
// 游戏机
Computer playStation = new Computer();
playStation.setCpu("i7");
playStation.setDisk("ssd");
playStation.setMemory("12g");
playStation.setScreen("curve surface");
playStation.setVideoCard("1080");
// 普通电脑
Computer commonComputer = new Computer();
commonComputer.setCpu("i5");
commonComputer.setDisk("hhd");
commonComputer.setMemory("4g");
commonComputer.setScreen("plane surface");
commonComputer.setVideoCard("720");
}
}
上面的程序太不专业了,调用方需要setter一大堆的东西,如果某一个部分不合理了,那么就用不了了。我们要做到的是,让用户爽,不需要setter那么多的东西。
优化
类图
程序
产品
public class Computer {
private String cpu;
private String memory;
private String disk;
private String videoCard;
private String screen;
//getter和setter以及toString省略
}
配置方案基类
public abstract class BaseAssemblyScheme {
protected Computer computer = new Computer();
public abstract void buildCpu();
public abstract void buildMemory();
public abstract void buildDisk();
public abstract void buildVideoCard();
public abstract void buildScreen();
public Computer generteComputer() {
return computer;
}
}
配置方案实现类
public class CommonAssemblyScheme extends BaseAssemblyScheme {
public void buildCpu() {computer.setCpu("i5");}
public void buildMemory() {computer.setMemory("4g");}
public void buildDisk() {computer.setDisk("ssd");}
public void buildVideoCard() {computer.setVideoCard("720");}
public void buildScreen() {computer.setScreen("plane surface");}
}
导演接口
public interface IMajor {
Computer construct();
void setBaseAssemblyScheme(BaseAssemblyScheme baseAssemblyScheme);
}
导演实现
public class Major implements IMajor{
private BaseAssemblyScheme baseAssemblyScheme;
public Major(BaseAssemblyScheme baseAssemblyScheme) {
this.baseAssemblyScheme = baseAssemblyScheme;
}
public void setBaseAssemblyScheme(BaseAssemblyScheme baseAssemblyScheme) {
this.baseAssemblyScheme = baseAssemblyScheme;
}
public Computer construct() {
baseAssemblyScheme.buildCpu();
baseAssemblyScheme.buildDisk();
baseAssemblyScheme.buildMemory();
baseAssemblyScheme.buildScreen();
baseAssemblyScheme.buildVideoCard();
return baseAssemblyScheme.generteComputer();
}
}
调用方
public class Main {
public static void main(String[] args) {
//专家,我要一台普通电脑
IMajor major = new Major(new CommonAssemblyScheme());
Computer commonComputer = major.construct();
System.out.println(commonComputer);
// 专家,我开始吃鸡了,我要一台高级一点的电脑
major.setBaseAssemblyScheme(new PlayStationAssemblyScheme());
Computer playStationComputer = major.construct();
System.out.println(playStationComputer);
}
}
优点
- 不需要知道对象的创建细节,只需要调用就可以了
- 可以写不同的建造者的实现方案,方便扩展,复合开闭原则
- 在建造者实现当中,可以定义对象的创建过程以及创建细节
缺点
- 产品组成基本相同的情况下才适合,有很多通用的属性
- 产品变化复杂的情况下,不利于使用,会难以理解
应用场景
- 产品是复杂的,例子用String没有体现这种复杂性,如果Cpu是一个对象,这个对象里面由嵌套了n层,就会更加明显。
- 属性之间的顺序互相依赖,例如要先装cpu再装电源等等
- 产品的创建独立于产品,通过第三方来创建
- 相同的创建过程可以有不同的结果,例如普通电脑和游戏电脑一样,相同的过程,但是结果不同
和工厂方法的不同
- 强调的重点不同,工厂倾向于生产一系列的产品,而建造者模式倾向于生产一个经过组合之后的产品
- 调用方式不同:工厂的调用时直接调生产对象的类,而建造者模式是调用指挥官,然后指挥官去调用生产对象的类