# 七大软件规划原则
# 规划形式-工厂形式
# 规划形式-单例形式
# 规划形式-原型形式
# 规划形式-战略形式
# 规划形式-职责链形式
# 规划形式-深度剖析代理形式
在咱们日子中的目标比方轿车,它是由车轮、车架、发动机等组合起来的目标,可是往往运用的人只想要一辆轿车并不想知道创立轿车的进程此刻就能够运用制作者形式。
在软件开发中,也存在许多类似轿车相同的杂乱目标,它们具有一系列成员特点,这些成员特点中有些是引用类型的成员目标。并且在这些杂乱目标中,还或许存在一些约束条件,如某些特点没有赋值则杂乱目标不能作为一个完整的产品运用;有些特点的赋值必须依照某个次序,一个特点没有赋值之前,另一个特点或许无法赋值等。
杂乱目标相当于一辆有待制作的轿车,而目标的特点相当于轿车的部件,制作产品的进程就相当于组合部件的进程。因为组合部件的进程很杂乱,因而,这些部件的组合进程往往被“外部化”到一个称作制作者的目标里,制作者返还给客户端的是一个现已制作结束的完整产品目标,而用户无须关心该目标所包括的特点以及它们的拼装方法,这便是制作者形式的形式动机。
制作者形式定义
制作者形式是一个将杂乱目标的构建进程与它的表明别离,使得相同的构建进程能够创立不同的表明,归于创立型形式,运用制作者形式关于用户而言只需求指定需求制作的类型就能够获取目标,制作进程及细节不需求了解。
能够看一下传统制作者形式UML类图: 其中首要的人物有四个:
- 产品(Product):要创立的产品类目标
- 制作者抽象(Builder):制作者的抽象类,规范产品目标的各个部分组成的制作,一般由子类实现详细的制作进程
- 制作者(ConcreteBuilder):详细的Builder类,依据不同的事务逻辑,详细化目标的各个组成部分的创立
- 调用者(Director):调用详细的制作者来创立目标的各个部分,在指导者中不触及详细产品的信息,只担任保证目标各部分完成创立或者按某种次序创立
传统形式代码示例
举一个肯德基的套餐的比如。肯德基有许多套餐,肯德基的服务员需求依据用户的要求提供对应的的套餐。
@Data
@ToString
public class Combo {
private String title;
private String Hamburger;
private String chickenWings;
private String drumstick;
private String cola;
public Combo(String title){
this.title = title;
}
}
public interface ComboBuilder {
Combo build();
void buildHamburger();
void buildChickenWings();
void buildDrumstick();
void buildCola();
}
public class BComboBuilder implements ComboBuilder{
private final Combo mCombo = new Combo("B套餐");
@Override
public void buildHamburger() {
mCombo.setHamburger("两个套餐");
}
@Override
public void buildChickenWings() {
mCombo.setChickenWings("五个鸡翅");
}
@Override
public void buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
}
@Override
public void buildCola() {
mCombo.setCola("两个可乐");
}
public Combo build(){
return this.mCombo;
}
}
public class AComboBuilder implements ComboBuilder {
private final Combo mCombo = new Combo("A套餐");
@Override
public void buildHamburger() {
mCombo.setHamburger("一个汉堡");
}
@Override
public void buildChickenWings() {
mCombo.setChickenWings("三个鸡翅");
}
@Override
public void buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
}
@Override
public void buildCola() {
mCombo.setCola("一个可乐");
}
public Combo build(){
return this.mCombo;
}
}
public class Waiter {
private final ComboBuilder builder;
public Combo getCombo(){
return this.builder.build();
}
public Waiter(ComboBuilder builder){
this.builder = builder;
}
public void setBuilder() {
this.builder.buildChickenWings();
this.builder.buildCola();
this.builder.buildDrumstick();
this.builder.buildHamburger();
}
}
public class Test {
public static void main(String[] args) {
AComboBuilder aComboBuilder = new AComboBuilder();
Waiter waiter = new Waiter(aComboBuilder);
waiter.setBuilder();
Combo combo = waiter.getCombo();
System.out.println(combo);
}
}
传统形式优化-链式编程
public class AComboBuilder implements ComboBuilder {
private final Combo mCombo = new Combo("A套餐");
@Override
public ComboBuilder buildHamburger() {
mCombo.setHamburger("一个汉堡");
return this;
}
@Override
public ComboBuilder buildChickenWings() {
mCombo.setChickenWings("三个鸡翅");
return this;
}
@Override
public ComboBuilder buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
return this;
}
@Override
public ComboBuilder buildCola() {
mCombo.setCola("一个可乐");
return this;
}
public Combo build(){
return this.mCombo;
}
}
public class Test {
public static void main(String[] args) {
AComboBuilder aComboBuilder = new AComboBuilder();
Combo combo = aComboBuilder.buildChickenWings()
.buildCola()
.buildDrumstick()
.buildHamburger()
.build();
System.out.println(combo);
}
}
如上图所示不需求再一个一个写一个一个赋值了直接链式编程就好,还有一点上述的写法弃用了Director
,个人感觉没必要硬着头皮要套传统形式的写法,也是能够有一些变通,首要是要适合自己的项目,假如便是一个目标的创立很杂乱咱们也能够将builder
内嵌到类中如下:
@Data
@ToString
public class Combo {
private String title;
private String Hamburger;
private String chickenWings;
private String drumstick;
private String cola;
public Combo(String title){
this.title = title;
}
public static class Builder {
private final Combo mCombo = new Combo("A套餐");
public Builder buildHamburger() {
mCombo.setHamburger("一个汉堡");
return this;
}
public Builder buildChickenWings() {
mCombo.setChickenWings("三个鸡翅");
return this;
}
public Builder buildDrumstick() {
mCombo.setDrumstick("三个鸡腿");
return this;
}
public Builder buildCola() {
mCombo.setCola("一个可乐");
return this;
}
public Combo build(){
return this.mCombo;
}
}
}
Combo combo = new Combo.Builder()
.buildChickenWings()
.buildCola()
.buildDrumstick()
.buildHamburger()
.build();
System.out.println(combo);
依据自己的项目需求随机变通
制作者形式在源码中的运用
这儿就举 StringBuilder
的比如吧
这种情况就很适用制作者形式应为在拼接字符串中为了提高性能需求做许多处理,假如放在外面每次运用都要调用那么多代码很不便利
制作者形式的运用场景
- 需求生成的产品目标有杂乱的内部结构,这些产品目标一般包括多个成员特点。
- 当你的目标的结构办法有三四个乃至更多的时分能够运用制作者形式代替
- 当初始化一个目标特别杂乱,参数多,并且许多参数都有默认值的时分
制作者形式优缺陷:
长处:
- 在制作者形式中,客户不必知道产品内部的组成细节
- 封装性好,创立和运用隔离
- 扩展性好,制作类直接独立,一定程度上解耦
缺陷:
- 产生剩余的制作类
- 产品内部发生变化,制作者都要修正,违反开闭原则一起修正成本也比较大
制作者形式和工厂形式的区别
- 制作者形式更加注重办法的调用次序,工厂形式注重创立目标
- 创立目标的力度不同,制作者形式创立杂乱的目标,由各种杂乱的部件组成,工程形式创立出来的都相同(这儿或许有人疑问为啥相同,应为制作者形式目标的一些特点咱们都是能够赋值的,能够有的有有的没有天然目标也就不相同了。工厂形式不相同只有一种创立方法要么特点全都有要么全没有所以相同)
- 重视维度不相同,工厂只重视目标的创立,制作者不仅要创立,还要知道这个目标是由那些部件组成的
- 制作者形式依据制作进程中的次序不相同,最终的目标部件组成也有或许是不相同的(那些不关系调用次序的类可便是相同的)