水果店生意越做越大,竞争力也越来越大,需要进一步吸引人气,那么就推出了套餐
有几个问题:
- 套餐包含各类水果的组合,较复杂(套餐后续会越来越复杂)。
- 套餐的创建步骤基本固定,设置价格/设置折扣/得到结算价。
- 会不断推出新的套餐。
这就需要推出一个业务流程
建造者模式
梳理业务流程

将业务流程抽象出来

//创建一个水果套餐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对象的构建
- new对象出来,然后set各种属性
缺点:必须得对象构建完成后,才能set属性值,中间可以插入其他操作(可以看成非原子操作) - 把所有属性作为构造器的入参
缺点:属性越多,构造器参数越多
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对象的好处是
- 在调用build()方法之前是不会创建出对象的,传统set方法,是先创建对象,再设置值
builder模式是先设置值,后创建对象。
这两者的区别是,传统set方法因为对象已经创建出来了,所以可以对对象做其他操作(如get属性值),
而build方法对象一创建出来就是设置好值的对象,这时候去获取属性值不会是null - 链式调用,传统set方法返回值是void,而且@Builder返回该对象的引用,这样设置值的时候,就不用一遍遍复制引用变量,然后点一下方法名,可以直接点出方法,使用更加优雅
网友评论