• (5)建造者模式


    一、概念

    建造者模式的定义是:将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式

    建造者模式,顾名思义的就是类似建房子,有一个固定的流程。

    建造者模式实现了依赖倒转原则,抽象不应该依赖细节,细节应该依赖于抽象。

    二、使用场景

    当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用建造者模式。

    建造者模式的角色定义,在建造者模式中存在以下4个角色:

    • Builder:为创建一个产品对象的各个部件指定抽象接口
    • ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口
    • Director:构造一个使用Builder接口的对象
    • Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程, 包含定义组成部件的类,包括将这些部件装配成最终产品的接口

    Director使用Builder创建Product

    三、代码示例

    场景:水果店推出水果套餐,老顾客优惠10元,节假日套餐优惠15元

    建造者模式,输入一系列参数,建造一个想要的结果

    问题:

    1、套餐包含各类水果的组合,较复杂(套餐后续会越来越复杂)。

    2、套餐的创建步骤基本固定,设置价格/设置折扣/得到结算价。

    3、会不断推出新的套餐。

    1、所有套餐都有这四个步骤。

    2、套餐会不断增加丰富。

    3、订单在结算套餐时,算法与具体套餐无关。

    4、会员套餐与假日套餐的配置,交给专业人员(老员工)来做。

    builder类,生产套餐接口(为创建一个产品对象的各个部件指定抽象接口)

    1. /**
    2. * 创建一个Builder类,实际的builder类负责创建套餐product对象。
    3. * 也是工厂,生产套餐
    4. */
    5. public interface Builder {
    6. void buildApple(int price, int num);
    7. void buildBanana(int price, int num);
    8. void buildOrange(int price, int num);
    9. /**
    10. * 返回创建的套餐
    11. * @return
    12. */
    13. FruitMeal getFruitMeal();
    14. }

    product类,套餐模板类-相当于模具

    1. /**
    2. * 创建一个水果套餐Meal类,套餐模板
    3. * 封装项目明细、折扣、结算金额
    4. * 这个是固定的,会变动的是价格
    5. */
    6. @Data
    7. public class FruitMeal {
    8. /**
    9. * 苹果--价格
    10. */
    11. private Apple apple;
    12. /**
    13. * 香蕉价格
    14. */
    15. private Banana banana;
    16. /**
    17. * 桔子价格
    18. */
    19. private Orange orange;
    20. /**
    21. * 红包
    22. */
    23. private int discount;
    24. /**
    25. * 套餐总价
    26. */
    27. private int totalPrice;
    28. /**
    29. * 返回总价
    30. * @return
    31. */
    32. public int cost() {
    33. return this.totalPrice;
    34. }
    35. /**
    36. * 展示明细
    37. */
    38. public void showTotalPrice() {
    39. System.out.println("套餐总价:" + totalPrice);
    40. }
    41. /**
    42. * 计算套餐总价
    43. */
    44. public void settleAccounts() {
    45. if (null != apple) {
    46. totalPrice += apple.getPrice() * apple.getNum();
    47. }
    48. if (null != orange) {
    49. totalPrice += orange.getPrice() * orange.getNum();
    50. }
    51. if (null != banana) {
    52. totalPrice += banana.getPrice() * banana.getNum();
    53. }
    54. // 折扣
    55. if (totalPrice > 0) {
    56. totalPrice -= discount;
    57. }
    58. }
    59. }

    建造节假日套餐,实现Builder类

    1. /**
    2. * 节假日套餐
    3. * 接收一系列价格参数
    4. * 输出一个结算套餐
    5. */
    6. public class HolidayBuilder implements Builder {
    7. private FruitMeal fruitMeal = new FruitMeal();
    8. @Override
    9. public void buildApple(int price, int num) {
    10. Apple apple = new Apple();
    11. apple.setPrice(price);
    12. apple.setNum(num);
    13. fruitMeal.setApple(apple);
    14. }
    15. @Override
    16. public void buildBanana(int price, int num) {
    17. Banana banana = new Banana();
    18. banana.setPrice(price);
    19. banana.setNum(num);
    20. fruitMeal.setBanana(banana);
    21. }
    22. @Override
    23. public void buildOrange(int price, int num) {
    24. Orange orange = new Orange();
    25. orange.setPrice(price);
    26. orange.setNum(num);
    27. fruitMeal.setOrange(orange);
    28. }
    29. /**
    30. * 获取套餐
    31. * @return
    32. */
    33. @Override
    34. public FruitMeal getFruitMeal() {
    35. // 设置优惠红包
    36. fruitMeal.setDiscount(15);
    37. // 结算
    38. fruitMeal.settleAccounts();
    39. return fruitMeal;
    40. }
    41. }

    建造老客套餐,实现Builder接口

    1. /**
    2. * 老客套餐
    3. */
    4. public class OldCustomerBuilder implements Builder {
    5. // 水果套餐
    6. private FruitMeal fruitMeal = new FruitMeal();
    7. @Override
    8. public void buildApple(int price, int num) {
    9. Apple apple = new Apple();
    10. apple.setPrice(price);
    11. apple.setNum(num);
    12. fruitMeal.setApple(apple);
    13. }
    14. @Override
    15. public void buildBanana(int price, int num) {
    16. Banana fruit = new Banana();
    17. fruit.setPrice(price);
    18. fruit.setNum(num);
    19. fruitMeal.setBanana(fruit);
    20. }
    21. @Override
    22. public void buildOrange(int price, int num) {
    23. Orange fruit = new Orange();
    24. fruit.setPrice(price);
    25. fruit.setNum(num);
    26. fruitMeal.setOrange(fruit);
    27. }
    28. @Override
    29. public FruitMeal getFruitMeal() {
    30. //折扣
    31. fruitMeal.setDiscount(10);
    32. // 计算总价
    33. fruitMeal.settleAccounts();
    34. return fruitMeal;
    35. }
    36. }

    收银台-导演类

    1. /**
    2. * 收银台---导演类
    3. */
    4. public class FruitMealController {
    5. /**
    6. * 选择老客套餐, 以下代码模板,轻易是不变的, 设置价格和数量
    7. * 一般是 spring注入方法,
    8. */
    9. public static FruitMeal selectOld() {
    10. Builder builder = new OldCustomerBuilder();
    11. builder.buildApple(120, 2);
    12. builder.buildBanana(80, 2);
    13. builder.buildOrange(50, 1);
    14. // builder水果套餐product
    15. return builder.getFruitMeal();
    16. }
    17. /**
    18. * 选择节假日套餐, 以下代码模板,轻易是不变的, 设置价格和数量
    19. * 一般是 spring注入方法,
    20. */
    21. public static FruitMeal selectHoliday() {
    22. Builder builder = new HolidayBuilder();
    23. builder.buildApple(120, 2);
    24. builder.buildBanana(80, 2);
    25. builder.buildOrange(50, 1);
    26. // builder水果套餐product
    27. return builder.getFruitMeal();
    28. }
    29. /**
    30. * 导演类通过build创建创建套餐,并计算价格
    31. */
    32. public static void main(String[] args) {
    33. FruitMeal fruitMeal = selectHoliday();
    34. fruitMeal.showTotalPrice();
    35. System.out.println("节假日套餐总花费: " + fruitMeal.cost());
    36. FruitMeal fruitMeal1 = selectOld();
    37. fruitMeal1.showTotalPrice();
    38. System.out.println("老客套餐总花费: " + fruitMeal1.cost());
    39. }
    40. }

    四、建造者模式<-异同->工厂方法模式

  • 相关阅读:
    CH8571 沁恒微 RISC-V EC 用芯片实验 (一)参考手册 第一章 接脚描述
    Redis缓存雪崩及解决办法
    数据分析神经网络模型图,神经网络模型数据处理
    C++ 丑数
    单向链表(Singly Linked List)
    Flask设置跨域
    STM32F103ZE单片机呼吸灯源代码
    3d可视化产品爆炸图案例
    builder(建造者模式)
    6.S081-9线程切换 - Thread Switching
  • 原文地址:https://blog.csdn.net/qq_17021569/article/details/125531627