建造者模式的定义是:将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式
建造者模式,顾名思义的就是类似建房子,有一个固定的流程。
建造者模式实现了依赖倒转原则,抽象不应该依赖细节,细节应该依赖于抽象。
当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用建造者模式。
建造者模式的角色定义,在建造者模式中存在以下4个角色:
Director使用Builder创建Product
场景:水果店推出水果套餐,老顾客优惠10元,节假日套餐优惠15元

建造者模式,输入一系列参数,建造一个想要的结果
问题:
1、套餐包含各类水果的组合,较复杂(套餐后续会越来越复杂)。
2、套餐的创建步骤基本固定,设置价格/设置折扣/得到结算价。
3、会不断推出新的套餐。

1、所有套餐都有这四个步骤。
2、套餐会不断增加丰富。
3、订单在结算套餐时,算法与具体套餐无关。
4、会员套餐与假日套餐的配置,交给专业人员(老员工)来做。

builder类,生产套餐接口(为创建一个产品对象的各个部件指定抽象接口)
- /**
- * 创建一个Builder类,实际的builder类负责创建套餐product对象。
- * 也是工厂,生产套餐
- */
- public interface Builder {
- void buildApple(int price, int num);
-
- void buildBanana(int price, int num);
-
- void buildOrange(int price, int num);
-
- /**
- * 返回创建的套餐
- * @return
- */
- FruitMeal getFruitMeal();
- }
product类,套餐模板类-相当于模具
- /**
- * 创建一个水果套餐Meal类,套餐模板
- * 封装项目明细、折扣、结算金额
- * 这个是固定的,会变动的是价格
- */
- @Data
- public class FruitMeal {
- /**
- * 苹果--价格
- */
- private Apple apple;
- /**
- * 香蕉价格
- */
- private Banana banana;
- /**
- * 桔子价格
- */
- private Orange orange;
- /**
- * 红包
- */
- private int discount;
- /**
- * 套餐总价
- */
- private int totalPrice;
-
- /**
- * 返回总价
- * @return
- */
- public int cost() {
- return this.totalPrice;
- }
-
- /**
- * 展示明细
- */
- public void showTotalPrice() {
- System.out.println("套餐总价:" + totalPrice);
- }
-
- /**
- * 计算套餐总价
- */
- public void settleAccounts() {
- if (null != apple) {
- totalPrice += apple.getPrice() * apple.getNum();
- }
-
- if (null != orange) {
- totalPrice += orange.getPrice() * orange.getNum();
- }
-
- if (null != banana) {
- totalPrice += banana.getPrice() * banana.getNum();
- }
- // 折扣
- if (totalPrice > 0) {
- totalPrice -= discount;
- }
- }
- }
建造节假日套餐,实现Builder类
- /**
- * 节假日套餐
- * 接收一系列价格参数
- * 输出一个结算套餐
- */
- public class HolidayBuilder implements Builder {
- private FruitMeal fruitMeal = new FruitMeal();
-
- @Override
- public void buildApple(int price, int num) {
- Apple apple = new Apple();
- apple.setPrice(price);
- apple.setNum(num);
- fruitMeal.setApple(apple);
- }
-
- @Override
- public void buildBanana(int price, int num) {
- Banana banana = new Banana();
- banana.setPrice(price);
- banana.setNum(num);
- fruitMeal.setBanana(banana);
- }
-
- @Override
- public void buildOrange(int price, int num) {
- Orange orange = new Orange();
- orange.setPrice(price);
- orange.setNum(num);
- fruitMeal.setOrange(orange);
- }
-
- /**
- * 获取套餐
- * @return
- */
- @Override
- public FruitMeal getFruitMeal() {
- // 设置优惠红包
- fruitMeal.setDiscount(15);
- // 结算
- fruitMeal.settleAccounts();
- return fruitMeal;
- }
- }
建造老客套餐,实现Builder接口
- /**
- * 老客套餐
- */
- public class OldCustomerBuilder implements Builder {
- // 水果套餐
- private FruitMeal fruitMeal = new FruitMeal();
-
- @Override
- public void buildApple(int price, int num) {
- Apple apple = new Apple();
- apple.setPrice(price);
- apple.setNum(num);
- fruitMeal.setApple(apple);
- }
-
- @Override
- public void buildBanana(int price, int num) {
- Banana fruit = new Banana();
- fruit.setPrice(price);
- fruit.setNum(num);
- fruitMeal.setBanana(fruit);
- }
-
- @Override
- public void buildOrange(int price, int num) {
- Orange fruit = new Orange();
- fruit.setPrice(price);
- fruit.setNum(num);
- fruitMeal.setOrange(fruit);
- }
-
- @Override
- public FruitMeal getFruitMeal() {
- //折扣
- fruitMeal.setDiscount(10);
- // 计算总价
- fruitMeal.settleAccounts();
- return fruitMeal;
- }
- }
收银台-导演类
- /**
- * 收银台---导演类
- */
- public class FruitMealController {
- /**
- * 选择老客套餐, 以下代码模板,轻易是不变的, 设置价格和数量
- * 一般是 spring注入方法,
- */
- public static FruitMeal selectOld() {
- Builder builder = new OldCustomerBuilder();
- builder.buildApple(120, 2);
- builder.buildBanana(80, 2);
- builder.buildOrange(50, 1);
- // builder水果套餐product
- return builder.getFruitMeal();
- }
-
- /**
- * 选择节假日套餐, 以下代码模板,轻易是不变的, 设置价格和数量
- * 一般是 spring注入方法,
- */
- public static FruitMeal selectHoliday() {
- Builder builder = new HolidayBuilder();
- builder.buildApple(120, 2);
- builder.buildBanana(80, 2);
- builder.buildOrange(50, 1);
- // builder水果套餐product
- return builder.getFruitMeal();
- }
-
- /**
- * 导演类通过build创建创建套餐,并计算价格
- */
- public static void main(String[] args) {
- FruitMeal fruitMeal = selectHoliday();
- fruitMeal.showTotalPrice();
- System.out.println("节假日套餐总花费: " + fruitMeal.cost());
- FruitMeal fruitMeal1 = selectOld();
- fruitMeal1.showTotalPrice();
- System.out.println("老客套餐总花费: " + fruitMeal1.cost());
- }
- }
