试想这样一个装修业务(吊顶、涂料),由于吊顶、涂料种类很多,因此可以组合成一些套餐。
主接口类:
public interface Matter {
String scene(); // 场景:涂料、吊顶
String brand(); //品牌
String model(); //型号
BigDecimal price(); //价格
String desc(); // 描述
}
吊顶实现类:
public class LevelOneCeiling implements Matter{
@Override
public String scene() {
return "吊顶";
}
@Override
public String brand() {
return "装修公司自带";
}
@Override
public String model() {
return "一级顶";
}
@Override
public BigDecimal price() {
return new BigDecimal(260);
}
@Override
public String desc() {
return "一级顶,离顶120-150mm";
}
}
public class LevelTwoCeiling implements Matter {
@Override
public String scene() {
return "吊顶";
}
@Override
public String brand() {
return "装修公司自带";
}
@Override
public String model() {
return "二级顶";
}
@Override
public BigDecimal price() {
return new BigDecimal(850);
}
@Override
public String desc() {
return "二级顶,往下吊20cm";
}
}
涂料实现类:
public class DuluxCoat implements Matter {
@Override
public String scene() {
return "涂料";
}
@Override
public String brand() {
return "多乐士";
}
@Override
public String model() {
return "第二代";
}
@Override
public BigDecimal price() {
return new BigDecimal(719);
}
@Override
public String desc() {
return "多乐士涂料";
}
}
public class LiBangCoat implements Matter {
@Override
public String scene() {
return "涂料";
}
@Override
public String brand() {
return "立邦";
}
@Override
public String model() {
return "默认级别";
}
@Override
public BigDecimal price() {
return new BigDecimal(650);
}
@Override
public String desc() {
return "立邦涂料";
}
}
套餐类:
//如果不止这三种套餐我们是不是得写很多if代码块呢?
public class DecorationPackageController {
public String getMatterList(BigDecimal area,Integer level){
List<Matter> list = new ArrayList<>();
BigDecimal price = BigDecimal.ZERO;
//套餐1
if(1 == level){
LevelTwoCeiling levelTwoCeiling = new LevelTwoCeiling();
DuluxCoat duluxCoat = new DuluxCoat();
list.add(levelTwoCeiling);
list.add(duluxCoat);
price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelTwoCeiling.price()));
price = price.add(area.multiply(new BigDecimal("1.4")).multiply(duluxCoat.price()));
}
// 套餐2
if (2 == level) {
LevelTwoCeiling levelTwoCeiling = new LevelTwoCeiling();
LiBangCoat liBangCoat = new LiBangCoat();
list.add(levelTwoCeiling);
list.add(liBangCoat);
price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelTwoCeiling.price()));
price = price.add(area.multiply(new BigDecimal("1.4")).multiply(liBangCoat.price()));
}
// 套餐3
if (3 == level) {
LevelOneCeiling levelOneCeiling = new LevelOneCeiling();
LiBangCoat liBangCoat = new LiBangCoat();
list.add(levelOneCeiling);
list.add(liBangCoat);
price = price.add(area.multiply(new BigDecimal("0.2")).multiply(levelOneCeiling.price()));
price = price.add(area.multiply(new BigDecimal("1.4")).multiply(liBangCoat.price()));
}
StringBuilder detail = new StringBuilder("\r\n-------------------------------------------------------\r\n" +
"装修清单" + "\r\n" +
"套餐等级:" + level + "\r\n" +
"套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元\r\n" +
"房屋面积:" + area.doubleValue() + " 平米\r\n" +
"材料清单:\r\n");
for (Matter matter: list) {
detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。\n");
}
return detail.toString();
}
测试类:
@Test
public void test_DecorationPackageController(){
DecorationPackageController decoration = new DecorationPackageController();
System.out.println(decoration.getMatterList(new BigDecimal("132.52"),1));
System.out.println(decoration.getMatterList(new BigDecimal("98.25"),2));
System.out.println(decoration.getMatterList(new BigDecimal("85.43"),3));
}
开始说实现三种套餐,我们很容易用if代码块实现,但是如果有十几种套餐呢?我们是不是得在一个类中写很多if代码块,这样不是说不好,功能起码实现了。但是一个类逻辑过于复杂不好维护。 我们可以这样想一个套餐是由两大类吊顶和涂料两个小种类组成的,这是不是可以用建造者模式进行改造。 建造者的核心是一个填充各种小种类的方法类,一个builder类来构建套餐。
填充种类方法接口:
public interface IMenu {
IMenu appendCeiling(Matter matter); //吊顶
IMenu appendCoat(Matter matter);//涂料
String getDetail();
}
填充种类方法实现类:
@NoArgsConstructor
public class DecorationPackageMenu implements IMenu {
private List<Matter> list = new ArrayList<>();//装修清单
private BigDecimal price = BigDecimal.ZERO;
private BigDecimal area; //面积
private String grade; //套餐
public DecorationPackageMenu(BigDecimal area, String grade) {
this.area = area;
this.grade = grade;
}
@Override
public IMenu appendCeiling(Matter matter) {
list.add(matter);
price = price.add(area.multiply(new
BigDecimal("0.2")).multiply(matter.price()));
return this;
}
@Override
public IMenu appendCoat(Matter matter) {
list.add(matter);
price = price.add(area.multiply(new BigDecimal("1.4")).multiply(matter.price()));
return this;
}
@Override
public String getDetail() {
StringBuilder detail = new StringBuilder("\r\n-------------------------------------------------------\r\n" +
"装修清单" + "\r\n" +
"套餐等级:" + grade + "\r\n" +
"套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元\r\n" +
"房屋面积:" + area.doubleValue() + " 平米\r\n" +
"材料清单:\r\n");
for (Matter matter: list) {
detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。\n");
}
return detail.toString();
}
}
Builder类:
public class Builder {
public IMenu levelOne(BigDecimal area) {
return new DecorationPackageMenu(area, "套餐1")
.appendCeiling(new LevelTwoCeiling())
.appendCoat(new DuluxCoat());
}
public IMenu levelTwo(BigDecimal area){
return new DecorationPackageMenu(area, "套餐2")
.appendCeiling(new LevelTwoCeiling())
.appendCoat(new LiBangCoat());
}
public IMenu levelThree(BigDecimal area){
return new DecorationPackageMenu(area, "套餐3")
.appendCeiling(new LevelOneCeiling())
.appendCoat(new LiBangCoat());
}
}
测试方法:
@Test
public void test_Builder(){
Builder builder = new Builder();
// 套餐1
System.out.println(builder.levelOne(new BigDecimal("132.52")).getDetail());
// 套餐2
System.out.println(builder.levelTwo(new BigDecimal("98.25")).getDetail());
// 套餐3
System.out.println(builder.levelThree(new BigDecimal("85.43")).getDetail());
}
以后再想新增套餐类就可以在bulider类里直接添加就可以了,构建者模式用来搞一个复杂对象的(由很多小种类对象组成)。