紧接着上节讲到抽象工厂模式,接下来讲建造者模式。

水果店随着业务发展,想要举行各类促销活动来提升人气。

  • 会员购买橘子+苹果+香蕉(可能还有别的水果)立减15元
  • 假日促销则橘子+苹果+香蕉(可能还有别的水果)立减10元

问题:

  • 1.套餐组合包含各类水果的组合,较复杂(后续套餐越来越复杂)。
  • 2.套餐的创建步骤基本确定,设置商品价格/设置折扣/得到结算价。
  • 3.会不断的推出新的套餐。

针对需求,我们需要考虑扩展性,针对上面三个问题,我们考虑用建造者模式来设计。

1.创建步骤

针对这几个步骤我们抽象出一个建造接口即builder接口用来创建套餐。
套餐是一个对象我们定义一个类封装好属性,主要是各个水果的价格,折扣价,还有套餐总价:

结构图:


代码如下:

//创建一个水果套餐Meal类public class FruitMeal {    private Apple apple;//苹果--属性包含价格    private Banana banana;//香蕉价格    private Orange orange;    //桔子价格    private int discount;//折扣价    private int totalPrice;//套餐总价    public void setDiscount(int discount) {        this.discount = discount;    }    public void setApple(Apple apple) {        this.apple = apple;    }    public void setBanana(Banana banana) {        this.banana = banana;    }    public void setOrange(Orange orange) {        this.orange = orange;    }    public int cost(){        return this.totalPrice;    }    public void init() {        if (null != apple){            totalPrice += apple.price();        }        if (null != orange){            totalPrice += orange.price();        }        if (null != banana){            totalPrice += banana.price();        }        if (totalPrice > 0){            totalPrice -= discount;        }    }    public void showItems() {        System.out.println("totalPrice:" + totalPrice);    }}

builder接口:

//创建一个Builder类,实际的builder类负责创建套餐FruitMeal 对象。public interface Builder {//也是工厂    void buildApple(int price);//设置苹果    void buildBanana(int price);//设置香蕉    void buildOrange(int price);//设置桔子    FruitMeal getFruitMeal();//返回创建的套餐}/** * 节假日套餐建造工厂 * */public class HolidayBuilder implements Builder {    private FruitMeal fruitMeal = new FruitMeal();    @Override    public void buildApple(int price) {        Apple apple = new Apple();        apple.setPrice(price);        fruitMeal.setApple(apple);    }    @Override    public void buildBanana(int price) {        Banana fruit = new Banana();        fruit.setPrice(price);        fruitMeal.setBanana(fruit);    }    @Override    public void buildOrange(int price) {        Orange fruit = new Orange("Peter",80);        fruit.setPrice(price);        fruitMeal.setOrange(fruit);    }    @Override    public FruitMeal getFruitMeal() {        fruitMeal.setDiscount(15);//折扣价格对一个套餐来,是固定的        fruitMeal.init();        return fruitMeal;    }}/** * 会员套餐建造工厂 *  */public class OldCustomerBuilder implements Builder {    private FruitMeal fruitMeal = new FruitMeal();    @Override    public void buildApple(int price) {        Apple apple = new Apple();        apple.setPrice(price);        fruitMeal.setApple(apple);    }    @Override    public void buildBanana(int price) {        Banana fruit = new Banana();        fruit.setPrice(price);        fruitMeal.setBanana(fruit);    }    @Override    public void buildOrange(int price) {        Orange fruit = new Orange("Peter",80);        fruit.setPrice(price);        fruitMeal.setOrange(fruit);    }    @Override    public FruitMeal getFruitMeal() {        fruitMeal.setDiscount(10);        fruitMeal.init();        return fruitMeal;    }} public class FruitMealController {//收银台---导演类    public void construct() {//        Builder builder = new HolidayBuilder();        Builder builder = new OldCustomerBuilder();//spring注入方法,        //以下代码模板,轻易是不变的        builder.buildApple(120);//创建苹果设置价格        builder.buildBanana(80);//创建香蕉设置香蕉价格        builder.buildOrange(50);//创建桔子设置价格        FruitMeal fruitMeal = builder.getFruitMeal();        int cost = fruitMeal.cost();        System.out.println("本套件花费:"+cost);    }    public static void main(String[] args) {        new FruitMealController().construct();    }}public class Apple implements Fruit {    private int price = 100;    public Apple(){    }    public Apple(int price){        this.price = price;    }    public void pack(AppleBag bag){        bag.pack();    }    @Override    public int price() {        return price;    }    @Override    public void draw() {        System.out.print("苹果红富士");    }    public void setPrice(int price) {        this.price = price;    }} public class Banana implements Fruit {    private int price = 60;    @Override    public int price() {        return price;    }    public void pack(BananaBag bag){        bag.pack();    }    @Override    public void draw() {        System.out.print("仙人蕉");    }        public void setPrice(int price) {        this.price = price;    }}public class Orange implements Fruit {    private String name = "";    private int price = 70;    public Orange(String name,int price){        this.price = price;        this.name = name;    }    public void pack(OrangeBag bag){        bag.pack();    }    @Override    public int price() {        return price;    }    @Override    public void draw() {        System.out.print("砂糖桔");    }    public void setPrice(int price) {        this.price = price;    }}        /** * 水果接口 */public interface Fruit {    int price();    void draw();    }

使用建造者模式,使用建造工厂(节假日套餐工厂丶会员套餐工厂)生产出套餐,每多一个套餐,新增一个建造工厂,这实际上是用了工厂方法模式
只是建造工厂有一定相同的步骤。

建造者模式类图

主要有:

  • 1是Builder接口,抽象出生产某个复杂的对象的步骤
  • 2复杂对象用一个类
  • 3Builder实现类

在业务需求开发中,适当的使用设计模式将大大提高系统的可扩展性可读性,业务场景需要多考虑清晰。