您当前的位置: 首页 >  ui

顧棟

暂无认证

  • 5浏览

    0关注

    227博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

建造者模式(Builder Pattern)

顧棟 发布时间:2021-05-28 20:34:46 ,浏览量:5

文章目录
  • 建造者模式(Builder Pattern)
    • 建造者模式的定义
    • 建造者模式的优点
    • 建造者模式的缺点
    • 建造者模式的结构
    • 建造者模式的实现
      • 物料部分
      • 产品部分
      • 建造类部分
      • 指挥者部分
      • 场景调用
    • 使用场景

建造者模式(Builder Pattern) 建造者模式的定义

指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

建造者模式的优点
  1. 各个具体的建造者相互独立,有利于系统的扩展。
  2. 客户端不必知道产品内部组成的细节,便于控制细节风险。
建造者模式的缺点
  1. 产品的组成部分必须相同,这限制了其使用范围。
  2. 如果产品的内部变化复杂,该模式会增加很多的建造者类。
建造者模式的结构

建造者(Builder)模式的主要角色如下。

  1. 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个滅部件。
  2. 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
  3. 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  4. 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
建造者模式的实现 物料部分
package org.donny.design.patterns.builderPattern;

import java.math.BigDecimal;

/**
 * 物料
 */
public interface IMatter {

    /**
     * 场景分别为地板、地砖、涂料、吊顶
     */
   public String scene();

    /**
     * 品牌
     */
   public String brand();

    /**
     * 型号
     */
   public String model();

    /**
     * 平米报价
     */
   public BigDecimal price();

    /**
     * 描述
     */
   public String describe();
}
package org.donny.design.patterns.builderPattern.matter.ceiling;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 吊顶原料
 * 品牌;装修公司自带
 * 型号:一级顶
 */
public class OneLevelCeiling implements IMatter {

    @Override
    public String scene() {
        return "吊顶";
    }

    @Override
    public String brand() {
        return "装修公司";
    }

    @Override
    public String model() {
        return "一层顶";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(160);
    }

    @Override
    public String describe() {
        return "只有一个120-150mm层次的吊顶";
    }

}
package org.donny.design.patterns.builderPattern.matter.ceiling;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 吊顶原料
 * 品牌;装修公司自带
 * 型号:二级顶
 */
public class TwoLevelCeiling  implements IMatter {

    @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 describe() {
        return "二级吊顶高度一般就往下吊20cm,要是层高很高,也可增加每级的厚度";
    }
    
}
package org.donny.design.patterns.builderPattern.matter.coat;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 涂料原料
 * 品牌:多乐士(Dulux)
 */
public class DuluxCoat  implements IMatter {

    @Override
    public String scene() {
        return "涂料";
    }

    @Override
    public String brand() {
        return "多乐士(Dulux)";
    }

    @Override
    public String model() {
        return "第二代";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(718);
    }

    @Override
    public String describe() {
        return "多乐士是阿克苏诺贝尔旗下的著名建筑装饰油漆品牌";
    }
    
}
package org.donny.design.patterns.builderPattern.matter.coat;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 涂料
 * 品牌;立邦
 */
public class LiBangCoat implements IMatter {

    @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 describe() {
        return "立邦";
    }

}
package org.donny.design.patterns.builderPattern.matter.floor;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 地板原料
 * 品牌;德尔(Der)
 */
public class DerFloor implements IMatter {

    @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 describe() {
        return "DER木地板制造商";
    }

}
package org.donny.design.patterns.builderPattern.matter.floor;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 地板原料
 * 品牌:圣象
 */
public class ShengXiangFloor implements IMatter {

    @Override
    public String scene() {
        return "地板";
    }

    @Override
    public String brand() {
        return "圣象";
    }

    @Override
    public String model() {
        return "一级";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(328);
    }

    @Override
    public String describe() {
        return "圣象地板";
    }

}
package org.donny.design.patterns.builderPattern.matter.tile;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 地砖原料
 * 品牌:东鹏瓷砖
 */
public class DongPengTile implements IMatter {

    @Override
    public String scene() {
        return "地砖";
    }

    @Override
    public String brand() {
        return "东鹏瓷砖";
    }

    @Override
    public String model() {
        return "10001";
    }

    @Override
    public BigDecimal price() {
        return new BigDecimal(112);
    }

    @Override
    public String describe() {
        return "东鹏瓷砖";
    }

}
package org.donny.design.patterns.builderPattern.matter.tile;

import org.donny.design.patterns.builderPattern.IMatter ;

import java.math.BigDecimal;

/**
 * 地砖原料
 * 品牌;马可波罗(MARCO POLO)
 */
public class MarcoPoloTile implements IMatter {

    @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 describe() {
        return "马可波罗品牌";
    }

}
产品部分
package org.donny.design.patterns.builderPattern;

public class Menu {

    private Matter celling;
    private Matter coat;
    private Matter floor;
    private Matter tile;

    private String getDetail;

    public Matter getCelling() {
        return celling;
    }

    public void setCelling(Matter celling) {
        this.celling = celling;
    }

    public Matter getCoat() {
        return coat;
    }

    public void setCoat(Matter coat) {
        this.coat = coat;
    }

    public Matter getFloor() {
        return floor;
    }

    public void setFloor(Matter floor) {
        this.floor = floor;
    }

    public Matter getTile() {
        return tile;
    }

    public void setTile(Matter tile) {
        this.tile = tile;
    }

    public String getGetDetail() {
        return getDetail;
    }

    public void setGetDetail(String getDetail) {
        this.getDetail = getDetail;
    }

}
建造类部分
public abstract class IMenuBuilder {

    public abstract Menu getMenu();
}
public class LuxuryMenuBuilder extends IMenuBuilder {

    private final Menu luxuryMenu = new Menu();
    private final List list = new ArrayList();
    /**
     * 装修价格
     */
    private BigDecimal price = BigDecimal.ZERO;

    /**
     * 面积
     */
    private final BigDecimal area;

    public LuxuryMenuBuilder(Double area) {
        this.area = new BigDecimal(area);
        this.luxuryMenu.setCelling(new TwoLevelCeiling());
        this.price = this.price.add(this.area.multiply(new BigDecimal("0.2")).multiply(luxuryMenu.getCelling().price()));
        this.luxuryMenu.setCoat(new DuluxCoat());
        this.price = price.add(this.area.multiply(new BigDecimal("1.4")).multiply(luxuryMenu.getCoat().price()));
        this.luxuryMenu.setFloor(new ShengXiangFloor());

        this.list.add(luxuryMenu.getFloor());
        this.list.add(luxuryMenu.getCoat());
        this.list.add(luxuryMenu.getCelling());
        this.luxuryMenu.setGetDetail(this.getDetail());
    }

    @Override
    public Menu getMenu() {
        return luxuryMenu;
    }

    public String getDetail() {
        StringBuilder detail = new StringBuilder("\r\n-------------------------------------------------------\r\n" +
                "装修清单" + "\r\n" +
                "套餐等级:欧式\r\n" +
                "套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元\r\n" +
                "房屋面积:" + area.doubleValue() + " 平米\r\n" +
                "材料清单:\r\n");

        for (Matter matter : this.list) {
            detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。\n");
        }

        return detail.toString();
    }
}
package org.donny.design.patterns.builderPattern;

import org.donny.design.patterns.builderPattern.matter.ceiling.LevelTwoCeiling;
import org.donny.design.patterns.builderPattern.matter.coat.LiBangCoat;
import org.donny.design.patterns.builderPattern.matter.tile.MarcoPoloTile;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class LightLuxuryMenuBuilder extends IMenuBuilder  {

    private final Menu lightLuxuryMenu = new Menu();
    private final List list = new ArrayList();
    /**
     * 装修价格
     */
    private BigDecimal price = BigDecimal.ZERO;

    /**
     * 面积
     */
    private final BigDecimal area;

    public LightLuxuryMenuBuilder(Double area) {
        this.area = new BigDecimal(area);
        this.lightLuxuryMenu.setCelling(new TwoLevelCeiling());
        this.price = this.price.add(this.area.multiply(new BigDecimal("0.2")).multiply(lightLuxuryMenu.getCelling().price()));
        this.lightLuxuryMenu.setCoat(new LiBangCoat());
        this.price = price.add(this.area.multiply(new BigDecimal("1.4")).multiply(lightLuxuryMenu.getCoat().price()));
        this.lightLuxuryMenu.setTile(new MarcoPoloTile());
        this.list.add(this.lightLuxuryMenu.getTile());
        this.list.add(this.lightLuxuryMenu.getCoat());
        this.list.add(this.lightLuxuryMenu.getCelling());
        this.lightLuxuryMenu.setGetDetail(this.getDetail());
    }

    @Override
    public Menu getMenu() {
        return this.lightLuxuryMenu;
    }

    public String getDetail() {
        StringBuilder detail = new StringBuilder("\r\n-------------------------------------------------------\r\n" +
                "装修清单" + "\r\n" +
                "套餐等级:田园"+ "\r\n" +
                "套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + " 元"+"\r\n" +
                "房屋面积:" + area.doubleValue() + " 平米"+"\r\n" +
                "材料清单:"+"\r\n");

        for (Matter matter : this.list) {
            detail.append(matter.scene()).append(":").append(matter.brand()).append("、").append(matter.model()).append("、平米价格:").append(matter.price()).append(" 元。");
        }

        return detail.toString();
    }
}

指挥者部分
public class Director {

    public Menu getLuxuryMenu(Double area) {
        return new LuxuryMenuBuilder(area).getMenu();
    }

    public Menu getLightLuxuryMenu(Double area) {
        return new LightLuxuryMenuBuilder(area).getMenu();
    }
}
场景调用
public class Client {

    public static void main(String[] args) {
        Director director =new Director();
        System.out.println(director.getLightLuxuryMenu(132.52D).getGetDetail());
        System.out.println(director.getLuxuryMenu(98.25D).getGetDetail());
    }
}
使用场景
  • 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。
  • 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身已经违反设计的最初目标。

本文主要参考:

  1. 小傅哥的《重学Java模式》
  2. 《设计模式之禅》第二版 秦小波
关注
打赏
1663402667
查看更多评论
立即登录/注册

微信扫码登录

0.0434s