(5)建造者模式

本文介绍了建造者模式在创建复杂对象时的应用,以水果套餐为例,展示了如何通过抽象Builder接口、具体建造者类、Director类和Product类来构建和定制不同类型的套餐。在代码示例中,分别构建了节假日套餐和老客套餐,并通过收银台类(Director)进行组装和计算价格,体现了建造者模式在处理多个可选参数和固定构建流程时的优势。
摘要由CSDN通过智能技术生成

一、概念

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

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

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

二、使用场景

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

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

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

Director使用Builder创建Product

三、代码示例

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

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

问题:

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

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

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

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

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

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

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

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

/**
 * 创建一个Builder类,实际的builder类负责创建套餐product对象。
 * 也是工厂,生产套餐
 */
public interface Builder {
    void setApple(int price, int num);
    void setBanana(int price, int num);
    void setOrange(int price, int num);

    /**
     * 返回创建的套餐
     * @return
     */
    FruitMeal build();
}

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

/**
 * 创建一个水果套餐Meal类,套餐模板
 * 封装项目明细、折扣、结算金额
 * 这个是固定的,会变动的是价格
 */
@Data
public class FruitMeal {
    /**
     * 苹果--价格
     */
    private Apple apple;
    /**
     * 香蕉价格
     */
    private Banana banana;
    /**
     * 桔子价格
     */
    private Orange orange;
    /**
     * 红包
     */
    private int discount;
    /**
     * 总价
     */
    private int totalPrice;

    /**
     * 展示明细
     */
    public void showTotalPrice() {
        System.out.println("苹果:" +"数量-"+apple.getNum() +",单价-"+apple.getPrice()+" 小结:"+apple.getNum()*apple.getPrice());
        System.out.println("香蕉:" +"数量-"+banana.getNum() +",单价-"+banana.getPrice()+" 小结:"+banana.getNum()*banana.getPrice());
        System.out.println("桔子:" +"数量-"+orange.getNum() +",单价-"+orange.getPrice()+" 小结:"+orange.getNum()*orange.getPrice());
        System.out.println("红包:" + discount);
    }

    /**
     * 结算
     */
    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 setApple(int price, int num) {
        fruitMeal.setApple(new Apple(price,num));
    }

    @Override
    public void setBanana(int price, int num) {
        fruitMeal.setBanana(new Banana(price,num));
    }

    @Override
    public void setOrange(int price, int num) {
        fruitMeal.setOrange(new Orange(price,num));
    }

    /**
     * 获取套餐
     * @return
     */
    @Override
    public FruitMeal build() {
        // 设置优惠红包
        fruitMeal.setDiscount(15);
        // 结算
        fruitMeal.settleAccounts();
        return fruitMeal;
    }
}

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

/**
 * 老客套餐
 * @author guxilong
 */
public class OldCustomerBuilder implements Builder {
    // 水果套餐
    private FruitMeal fruitMeal = new FruitMeal();

    @Override
    public void setApple(int price, int num) {
        fruitMeal.setApple(new Apple(price,num));
    }

    @Override
    public void setBanana(int price, int num) {
        fruitMeal.setBanana(new Banana(price,num));
    }

    @Override
    public void setOrange(int price, int num) {
        fruitMeal.setOrange(new Orange(price,num));
    }

    @Override
    public FruitMeal build() {
        //折扣
        fruitMeal.setDiscount(10);
        // 计算总价
        fruitMeal.settleAccounts();
        return fruitMeal;
    }
}

收银台-导演类

/**
 * 收银台---导演类
 */
public class Director {
    /**
     * 选择老客套餐, 以下代码模板,轻易是不变的, 设置价格和数量
     * 一般是 spring注入方法,
     */
    public static FruitMeal selectOld() {
        Builder builder = new OldCustomerBuilder();
        builder.setApple(120, 2);
        builder.setBanana(80, 2);
        builder.setOrange(50, 1);
        // 构建1个套餐对象
        return builder.build();
    }

    /**
     * 选择节假日套餐, 以下代码模板,轻易是不变的, 设置价格和数量
     * 一般是 spring注入方法,
     */
    public static FruitMeal selectHoliday() {
        Builder builder = new HolidayBuilder();
        builder.setApple(120, 2);
        builder.setBanana(80, 2);
        builder.setOrange(50, 1);
        // 构建1个套餐对象
        return builder.build();
    }
}
public class BuildTest {
    /**
     * 导演类通过build创建创建套餐,并计算价格
     */
    public static void main(String[] args) {
        // 选则节假日套餐
        FruitMeal fruitMeal = Director.selectHoliday();
        fruitMeal.showTotalPrice();
        System.out.println("节假日套餐总花费: " + fruitMeal.getTotalPrice());

        // 选则节假日套餐
        FruitMeal fruitMeal1 = Director.selectOld();
        fruitMeal1.showTotalPrice();
        System.out.println("老客套餐总花费: " + fruitMeal1.getTotalPrice());
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值