创建型模式:建造者模式
文章目录
建造者模式
1、建造者模式:介绍
- 建造者模式
- 核心目的是:通过使用多个简单对象一步步地构建出一个复杂对象。
- 根据相同的物料、不同的组装方式产生出具体内容,就是建造者模式的最终意图
- 即将一个复杂的构建与其表示分离,用同样的构建过程可以创建不同的表示
2、建造者模式:模拟场景
- 装修套餐选配场景
- 很多装修公司都会提供一些套餐服务,一般会有:豪华欧式、轻奢田园和现代简约 装修服务套餐。
- 这些套餐的背后是不同装修材料和设计风格的组合
- 一级顶、二级顶
- 多乐士涂料、立邦涂料
- 圣像地板、德尔地板
- 马可波罗地砖、东鹏地砖
- 按照不同的套餐价格,选取不同的品牌进行组合,最终再结合装修面积给出整体报价
3、建造者模式:场景模拟工程
0、工程结构
lino-design-6.0
|——src
|——main
|--java
|--com.lino.design
|--ceiling
|--LevelOneCeiling.java
|--LevelTwoCeiling.java
|--coat
|--DuluxCoat.java
|--LiBangCoat.java
|--floor
|--DerFloor.java
|--ShengXiangFloor.java
|--tile
|--DongPengTile.java
|--MarcoPoloTile.java
|--Matter.java
- 在模拟的装修材料工程中,提供了如下类:
-
ceiling
(吊顶材料)包:LevelOneCeiling
,LevelTwoCeiling
-
coat
(涂料材料)包:DuluxCoat
,LiBangCoat
-
floor
(地板材料)包:DerFloor
,ShengXiangFloor
-
tile
(地砖材料)包:DongPengTile
,MarcoPoloTile
-
1、装修材料接口
- 装修材料接口提供了基本的方法获取信息,以保证所有不同规格和种类的装修材料都可以按照统一标准被获取。
import java.math.BigDecimal;
/**
* @description: 装修物料
*/
public interface Matter {
/**
* 场景;地板、地砖、涂料、吊顶
*
* @return String
*/
String scene();
/**
* 品牌
*
* @return String
*/
String brand();
/**
* 型号
*
* @return String
*/
String model();
/**
* 平米报价
*
* @return BigDecimal
*/
BigDecimal price();
/**
* 描述
*
* @return String
*/
String desc();
}
2、吊顶材料(ceiling)
- 一级顶
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 吊顶:一级顶
*/
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";
}
}
- 二级顶
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 吊顶:二级顶
*/
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,要是层高很高,也可增加每级的厚度";
}
}
3、涂料材料(coat)
- 多乐士
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 涂料:多乐士(Dulux)
*/
public class DuluxCoat implements Matter {
@Override
public String scene() {
return "涂料";
}
@Override
public String brand() {
return "多乐士(Dulux)";
}
@Override
public String model() {
return "第二代";
}
@Override
public BigDecimal price() {
return new BigDecimal(719);
}
@Override
public String desc() {
return "多乐士是阿克苏诺贝尔旗下的著名建筑装饰油漆品牌,产品畅销于全球100个国家,每年全球有5000万户家庭使用多乐士油漆。";
}
}
- 立邦
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 涂料:立邦
*/
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 "立邦始终以开发绿色产品、注重高科技、高品质为目标,以技术力量不断推进科研和开发,满足消费者需求。";
}
}
4、地板材料(floor)
- 德尔
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 地板:德尔(Der)
*/
public class DerFloor implements Matter {
@Override
public String scene() {
return "地板";
}
@Override
public String brand() {
return "德尔(Der)";
}
@Override
public String model() {
return "A+";
}
@Override
public BigDecimal price() {
return new BigDecimal(119);
}
@Override
public String desc() {
return "DER德尔集团是全球领先的专业木地板制造商,北京2008年奥运会家装和公装地板供应商";
}
}
- 圣像
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 地板:圣象
*/
public class ShengXiangFloor implements Matter {
@Override
public String scene() {
return "地板";
}
@Override
public String brand() {
return "圣象";
}
@Override
public String model() {
return "一级";
}
@Override
public BigDecimal price() {
return new BigDecimal(318);
}
@Override
public String desc() {
return "圣象地板是中国地板行业著名品牌。圣象地板拥有中国驰名商标、中国名牌、国家免检、中国环境标志认证等多项荣誉。";
}
}
5、地砖材料(tile)
- 东鹏
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 地砖:东鹏瓷砖
*/
public class DongPengTile implements Matter {
@Override
public String scene() {
return "地砖";
}
@Override
public String brand() {
return "东鹏瓷砖";
}
@Override
public String model() {
return "10001";
}
@Override
public BigDecimal price() {
return new BigDecimal(102);
}
@Override
public String desc() {
return "东鹏瓷砖以品质铸就品牌,科技推动品牌,口碑传播品牌为宗旨,2014年品牌价值132.35亿元,位列建陶行业榜首。";
}
}
- 马克波罗
import com.lino.design.Matter;
import java.math.BigDecimal;
/**
* @description: 地砖:马可波罗(MARCO POLO)
*/
public class MarcoPoloTile implements Matter {
@Override
public String scene() {
return "地砖";
}
@Override
public String brand() {
return "马可波罗(MARCO POLO)";
}
@Override
public String model() {
return "缺省";
}
@Override
public BigDecimal price() {
return new BigDecimal(140);
}
@Override
public String desc() {
return "“马可波罗”品牌诞生于1996年,作为国内最早品牌化的建陶品牌,以“文化陶瓷”占领市场,享有“仿古砖至尊”的美誉。";
}
}
4、建造者模式:代码实现
0、工程结构
lino-design-6.0
|——src
|——main
|--java
|--com.lino.builder
|--Builder.java
|--DecorationPackageMenu.java
|--IMenu.java
|——test
|--java
|--com.lino.test
|--Test.java
- 建造者模式代码工程有三个核心类,这三个核心类是建造者模式的具体实现。
-
Builder
:建造者类具体的各种组装,都由此类实现。 -
DecorationPackageMenu
:是IMenu
接口的实现类,主要承载建造过程中的填充器,相当于一套承载物料和创建者中间衔接的内容
-
1、定义装修包接口
- 装修包接口定义了填充 吊顶、涂料、地板、地砖 各种材料的方法,以及最终提供获取全部明细的方法
import com.lino.design.Matter;
/**
* @description: 装修包接口
*/
public interface IMenu {
/**
* 吊顶
*
* @param matter 装修物料
* @return 装修包接口
*/
IMenu appendCeiling(Matter matter);
/**
* 涂料
*
* @param matter 装修物料
* @return 装修包接口
*/
IMenu appendCoat(Matter matter);
/**
* 地板
*
* @param matter 装修物料
* @return 装修包接口
*/
IMenu appendFloor(Matter matter);
/**
* 地砖
*
* @param matter 装修物料
* @return 装修包接口
*/
IMenu appendTile(Matter matter);
/**
* 明细
*
* @return String
*/
String getDetail();
}
2、实现装修包接口
- 在装修包的实现中,每一种方法都返回了this对象本身,可以非常方便地用于连续填充各种物料。
- 在填充时也会根据物料计算相应面积的报价,吊顶和涂料按照面积乘于单价计算
- 最后,同样提供了统一的获取装修清单的明细方法
import com.lino.design.Matter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 装修包接口实现类
*/
public class DecorationPackageMenu implements IMenu {
/**
* 装修清单
*/
private List<Matter> list = new ArrayList<>();
/**
* 装修价格
*/
private BigDecimal price = BigDecimal.ZERO;
/**
* 面积
*/
private BigDecimal area;
/**
* 装修等级;豪华欧式、轻奢田园、现代简约
*/
private String grade;
public DecorationPackageMenu() {
}
public DecorationPackageMenu(Double area, String grade) {
this.area = new BigDecimal(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 IMenu appendFloor(Matter matter) {
list.add(matter);
price = price.add(area.multiply(matter.price()));
return this;
}
@Override
public IMenu appendTile(Matter matter) {
list.add(matter);
price = price.add(area.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();
}
}
3、建造者类创建
- 统一的建造方式通过不同物料填充出不同的装修风格:豪华欧式、轻奢田园、现代简约
import com.lino.design.ceiling.LevelOneCeiling;
import com.lino.design.ceiling.LevelTwoCeiling;
import com.lino.design.coat.DuluxCoat;
import com.lino.design.coat.LiBangCoat;
import com.lino.design.floor.ShengXiangFloor;
import com.lino.design.tile.DongPengTile;
import com.lino.design.tile.MarcoPoloTile;
/**
* @description: 建造者类
*/
public class Builder {
/**
* 豪华欧式:吊顶,二级顶,涂料,多乐士,地板,圣象
*
* @param area 面积
* @return IMenu
*/
public IMenu levelOne(Double area) {
return new DecorationPackageMenu(area, "豪华欧式")
.appendCeiling(new LevelTwoCeiling())
.appendCoat(new DuluxCoat())
.appendFloor(new ShengXiangFloor());
}
/**
* 豪华欧式:吊顶,二级顶,涂料,立邦,地砖,马可波罗
*
* @param area 面积
* @return IMenu
*/
public IMenu levelTwo(Double area) {
return new DecorationPackageMenu(area, "轻奢田园")
.appendCeiling(new LevelTwoCeiling())
.appendCoat(new LiBangCoat())
.appendTile(new MarcoPoloTile());
}
/**
* 豪华欧式:吊顶,二级顶,涂料,立邦,地板,东鹏
*
* @param area 面积
* @return IMenu
*/
public IMenu levelThree(Double area) {
return new DecorationPackageMenu(area, "现代简约")
.appendCeiling(new LevelOneCeiling())
.appendCoat(new LiBangCoat())
.appendTile(new DongPengTile());
}
}
5、单元测试
- 使用建造者模式分别创建出三种装修套餐的价格,获取详情信息并进行输出
-
levelOne
,levelTwo
,levelThree
对应三种装修风格:豪华欧式、轻奢田园、现代简约 - 入参是信息是房屋面积,最终获取装修报价单。
-
import com.lino.builder.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @description: 测试类
*/
public class Test {
@org.junit.Test
public void testBuilder() throws Exception {
// 建造者类
Builder builder = new Builder();
// 豪华欧式
System.out.println(builder.levelOne(132.52D).getDetail());
// 轻奢田园
System.out.println(builder.levelTwo(98.25D).getDetail());
// 现代简约
System.out.println(builder.levelThree(85.43D).getDetail());
}
}
- 测试结果
-------------------------------------------------------
装修清单
套餐等级:豪华欧式
套餐价格:198064.39 元
房屋面积:132.52 平米
材料清单:
吊顶:装修公司自带、二级顶、平米价格:850 元。
涂料:多乐士(Dulux)、第二代、平米价格:719 元。
地板:圣象、一级、平米价格:318 元。
-------------------------------------------------------
装修清单
套餐等级:轻奢田园
套餐价格:119865.00 元
房屋面积:98.25 平米
材料清单:
吊顶:装修公司自带、二级顶、平米价格:850 元。
涂料:立邦、默认级别、平米价格:650 元。
地砖:马可波罗(MARCO POLO)、缺省、平米价格:140 元。
-------------------------------------------------------
装修清单
套餐等级:现代简约
套餐价格:90897.52 元
房屋面积:85.43 平米
材料清单:
吊顶:装修公司自带、一级顶、平米价格:260 元。
涂料:立邦、默认级别、平米价格:650 元。
地砖:东鹏瓷砖、10001、平米价格:102 元。
4、建造者模式:总结
-
选择建造者模式的条件
- 当一些基本材料不变,而其组合经常变化时。
-
满足单一职责原则及可复用的技术,建造者独立、易扩展、便于控制细节风险。
-
缺点:出现特别多的物料及组合时,类的不断扩展也会造成难以维护的问题。
- 解决:可以把重复的内容抽象到数据库中,按照需要配置,减少大量的重复代码。