用示例代码来帮你了解建造者模式
对于“设计模式”这个词大家肯定都不陌生,很多框架也用到了设计模式,但是大部分的开发者应该是没有深入的了解过,我准备硬肝下这23设计模式作为专题文章的开端,一共23种设计模式,我尽量在<23天肝完。
为什么要学习设计模式:https://blog.youkuaiyun.com/kaituozhe_sh/article/details/107922339
在我大学四年,对设计模式也没有什么概念,写代码就想着能实现就可以了,不会有设计模式那样的思想,但是当学习到了框架的时候,对于设计模式才有了一些更深入的了解,使用设计模式的代码在扩展性上会比暴力的代码更容易维护,特别是当一个程序猿离职了后,你去接手它的代码,里面是一大堆if else,这样真的会崩溃,修改都不知道从何下手
硬肝系列目录
创建型模式
结构型模式
行为型模式
2021/3/16原版
一、为什么要使用建造者模式?
现如今需求的不断变化,类中参数的不断增多,对于构造方法来说的确不太友好;用一个例子来说明吧,对于麦当劳来说,这么多种类的食物可以根据购买者来自主选择搭配,如果用普通的构造方法来实现的话,这样搭配的种类就非常多了,这时候我们就可以选择一种设计模式,也就是建造者模式,建造者模式(在创建一个对象的时 我们并不直接对操作对象,而是通过Builder类来存储参数,这个类往往就是建造类。
看看下面一个通过静态内部类实现的例子
用途:使得类可以以链式方法实例化对象
意义:其实现是静态内部类的典型应用,可以让大家很好理解静态内部类的意义
package designModels.BuilderModel03.model01;
public class McDonald {
//汉堡
private int hamburger;
//双层汉堡
private int doubleHamburger;
//玉米棒
private int corn;
//辣翅
private int spicyChicken;
//汉堡
private int fishBurger;
//可口可乐
private int cocaCola;
//新建一个内部Builder类,来预存传过来的食物
public static class Builder{
//汉堡
private int hamburger;
//双层汉堡
private int doubleHamburger;
//玉米棒
private int corn;
//辣翅
private int spicyChicken;
//汉堡
private int fishBurger;
//可口可乐
private int cocaCola;
public Builder(){}
public int getHamburger() {
return hamburger;
}
public Builder BuilderHamburger(int hamburger) {
this.hamburger = hamburger;
System.out.println("加" + hamburger + " 个汉堡");
return this;
}
public int getDoubleHamburger() {
return doubleHamburger;
}
public Builder BuilderDoubleHamburger(int doubleHamburger) {
this.doubleHamburger = doubleHamburger;
System.out.println("加" + doubleHamburger + " 个双层汉堡");
return this;
}
public int getCorn() {
return corn;
}
public Builder BuilderCorn(int corn) {
this.corn = corn;
System.out.println("加" + corn + " 根玉米棒");
return this;
}
public int getSpicyChicken() {
return spicyChicken;
}
public Builder BuilderSpicyChicken(int spicyChicken) {
this.spicyChicken = spicyChicken;
System.out.println("加" + spicyChicken + " 对辣翅");
return this;
}
public int getFishBurger() {
return fishBurger;
}
public Builder BuilderFishBurger(int fishBurger) {
this.fishBurger = fishBurger;
System.out.println("加" + fishBurger + " 个鳕鱼堡");
return this;
}
public int getCocaCola() {
return cocaCola;
}
public Builder BuilderCocaCola(int cocaCola) {
this.cocaCola = cocaCola;
System.out.println("加" + cocaCola + " 杯cocaCola");
return this;
}
//点完餐后调用此方法,新建外部类对象,将预存的信息作为入参
//传输给外部类构造方法
public McDonald build(){
return new McDonald(this);
}
}
//接收内部类传过来的参数
private McDonald(Builder builder) {
this.hamburger = builder.hamburger;
this.doubleHamburger = builder.doubleHamburger;
this.corn = builder.corn;
this.spicyChicken = builder.spicyChicken;
this.fishBurger = builder.fishBurger;
this.cocaCola = builder.cocaCola;
}
public static void main(String[] args) {
McDonald builder = new McDonald.Builder().BuilderCocaCola(2)
.BuilderCorn(2).BuilderDoubleHamburger(1).build();
}
}
打印结果:
加2 杯cocaCola
加2 根玉米棒
加1 个双层汉堡
使用一个建造类来帮我们预存信息,当预存完毕时即可将所预存的信息传到外部类作为入参,即可获取到预存的信息。
上面这种方式实现建造者模式缺陷还是很大的,所以我下面又将它进行了一个小改造
新建一个食物接口:
package designModels.BuilderModel03.model02;
import java.math.BigDecimal;
public interface Food {
String name();
BigDecimal price();
}
食物接口的定义,就将所有食物都做了一个规范,下面为接口实现类
import designModels.BuilderModel03.model02.Food;
import java.math.BigDecimal;
//可乐
public class cocaCola implements Food {
@Override
public String name() {
return "cocaCola";
}
@Override
public BigDecimal price() {
return new BigDecimal(13);
}
}
//玉米棒
public class corn implements Food {
@Override
public String name() {
return "corn";
}
@Override
public BigDecimal price() {
return new BigDecimal(16);
}
}
//双层汉堡
public class doubleHamburger implements Food {
@Override
public String name() {
return "doubleHamburger";
}
@Override
public BigDecimal price() {
return new BigDecimal(52);
}
}
//鳕鱼堡
public class fishBurger implements Food {
@Override
public String name() {
return "fishBurger";
}
@Override
public BigDecimal price() {
return new BigDecimal(32);
}
}
//汉堡
public class hamburger implements Food {
@Override
public String name() {
return "hamburger";
}
@Override
public BigDecimal price() {
return new BigDecimal(36);
}
}
//辣翅
public class spicyChicken implements Food {
@Override
public String name() {
return "spicyChicken";
}
@Override
public BigDecimal price() {
return new BigDecimal(18);
}
}
定义一菜单接口:
package designModels.BuilderModel03.model02;
public interface McMenu {
//入参为food,food里面包含了多种食物的信息
McMenu append(Food food);
//打印菜单
String printMenu();
}
建造类(菜单实现类)
package designModels.BuilderModel03.model02.impl;
import designModels.BuilderModel03.model02.McMenu;
import designModels.BuilderModel03.model02.Food;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class Builder implements McMenu {
List<Food> foodList = new ArrayList<>();
BigDecimal price = new BigDecimal(0);
@Override
public McMenu append(Food food) {
foodList.add(food);
price = price.add(food.price());
return this;
}
@Override
public String printMenu() {
StringBuilder str = new StringBuilder();
for (Food food:foodList) {
str.append("食品名称:" + food.name() + "----- 单价:" + food.price() + "\n");
}
str.append("all price :" + price);
return str.toString();
}
public static void main(String[] args) {
String menu = new Builder().append(new cocaCola()).append(new corn()).append(new fishBurger()).printMenu();
System.out.println(menu);
}
}
打印结果:
食品名称:cocaCola----- 单价:13
食品名称:corn----- 单价:16
食品名称:fishBurger----- 单价:32
all price :61
在一些基本的原料基本不变、组合经常变化的情况下,我们就可以使用这种建造者设计模式来实现
完成:TO: 2021/3/16 16:33
2021/3/22第一次修改
今天看文章的时候注意到了一个问题,建造者模式应该是用户的重点为最终的结果、且不知道建造内部的细节,而我我原来写的食物搭配的例子容易引起误会,因为这种搭配是呈现在客户眼前的,他知道了其中的细节,这里我再给大家举一个例子,也是以汉堡为例,我做一包薯条,建造者模式的意思就是说我不管你怎么做的,你最后给我一包汉堡就行
首先定义一个制作汉堡步骤接口
public interface Hamburger {
void step1();
void step2();
void step3();
void step4();
}
创建汉堡类并实现上面的接口
public class HamburgerImpl implements Hamburger{
@Override
public void step1() {
System.out.println("准备面包");
}
@Override
public void step2() {
System.out.println("准备菜叶子");
}
@Override
public void step3() {
System.out.println("准备肉排");
}
@Override
public void step4() {
System.out.println("组合蟹黄堡");
}
private static class Builder{
public Builder(HamburgerImpl hamburger){
hamburger.step1();
hamburger.step2();
hamburger.step3();
hamburger.step4();
System.out.println("可以售卖");
}
}
}
测试代码
public static void main(String[] args) {
Builder builder = new Builder(new HamburgerImpl());
}
实现结果
准备面包
准备菜叶子
准备肉排
组合蟹黄堡
可以售卖