(五)建造者模式

2019-07-21  本文已影响0人  feiry

水果店生意越做越大,竞争力也越来越大,需要进一步吸引人气,那么就推出了套餐

有几个问题:

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

这就需要推出一个业务流程

建造者模式

梳理业务流程

套餐业务流程
将业务流程抽象出来 业务关系图
//创建一个水果套餐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);
    }
}
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 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();
    }

}

这样就能按照业务流程走了,有点像模板方法模式,Bulider接口其实和工厂方法模式很像

常用的场景

JavaBean对象的构建

public class Example<T> {
    private T foo;
    private String bar;

    public Example() {
    }

    public Example(T foo, String bar) {
        this.foo = foo;
        this.bar = bar;
    }

    public T getFoo() {
        return foo;
    }

    public void setFoo(T foo) {
        this.foo = foo;
    }

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }
}

lombok有提供builder模式的注解

@Builder
public class Example<T> {
    private T foo;
    private String bar;
}

等同于

class Example<T> {
    private T foo;
    private String bar;
    
    private Example(T foo, String bar) {
        this.foo = foo;
        this.bar = bar;
    }
    
    public static <T> ExampleBuilder<T> builder() {
        return new ExampleBuilder<T>();
    }
    
    public static class ExampleBuilder<T> {
        private T foo;
        private String bar;
        
        private ExampleBuilder() {}
        
        public ExampleBuilder foo(T foo) {
            this.foo = foo;
            return this;
        }
        
        public ExampleBuilder bar(String bar) {
            this.bar = bar;
            return this;
        }
        
        @java.lang.Override public String toString() {
            return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")";
        }
        
        public Example build() {
            return new Example(foo, bar);
        }
    }
   }

使用方法如下

@Builder
public class Example<T> {
    private T foo;
    private String bar;

    public static void main(String[] args) {
        ExampleBuilder<String> builder = Example.builder();//获取对象的建造者
        Example<String> build = builder.bar("1")
                .foo("2")
                .build();//链式构建对象
        System.out.println(build);
    }
}

这种Builder模式构建Bean对象的好处是

  1. 在调用build()方法之前是不会创建出对象的,传统set方法,是先创建对象,再设置值
    builder模式是先设置值,后创建对象。
    这两者的区别是,传统set方法因为对象已经创建出来了,所以可以对对象做其他操作(如get属性值),
    而build方法对象一创建出来就是设置好值的对象,这时候去获取属性值不会是null
  2. 链式调用,传统set方法返回值是void,而且@Builder返回该对象的引用,这样设置值的时候,就不用一遍遍复制引用变量,然后点一下方法名,可以直接点出方法,使用更加优雅
上一篇 下一篇

猜你喜欢

热点阅读