如果一个对象由多个元素组成,而且这些元素可组成不同的对象,用构造者模式去分离出这个对象的构造过程。
构造者模式 Builder
问题
An application needs to create the elements of a complex aggregate. The specification for the aggregate exists on secondary storage and one of many representations needs to be built in primary storage.
意图:
- Separate the construction of a complex object from its representation so that the same construction process can create different representations.
- Parse a complex representation, create one of several targets.
代码
例:比如一个网店卖包子=10块,饺子=20快,馒头=50块,很多用户一次买两样或三样都要点几次,于是使用构造者模式可以构造一个“套餐”,包子和饺子一走卖省5元,三个一起买省10元,除了方便用户,还带来了促销效果。
代码1:元数据
package com.xdnote.DesignPattern.creational.bulider;
public enum Product {
PRODUCT1("包子",10),
PRODUCT2("馒头",50),
PRODUCT3("饺子",20);
private String name;
private int price;
private Product(String name1,int price1){
this.name=name1;
this.price=price1;
}
public String getName(){
return this.name;
}
public int getPirce(){
return this.price;
}
}
代码2:套餐类,用户买一个套餐就可知道套餐里面有什么内容
package com.xdnote.DesignPattern.creational.bulider;
import java.util.ArrayList;
import java.util.List;
public class Combo {
//套餐包含的产品
private List<Product> product ;
//套餐折扣
private int discount;
public Combo(){
this.product=new ArrayList<Product>();
this.discount=0;
}
public void setDiscount(int discount){
this.discount = discount;
}
public void addProduct(Product p){
this.product.add(p);
}
public String toString(){
int length=product.size();
StringBuffer sb=new StringBuffer("买了");
int total = 0;
for(int i=0;i<length;i++){
Product p = product.get(i);
total+=p.getPirce();
sb.append(p.getName()).append(" ");
}
sb.append(length).append("件物品");
sb.append("共").append(total).append("元");
sb.append("套餐优惠").append(this.discount).append("元");
sb.append("共").append(total-this.discount).append("元");
return sb.toString();
}
}
代码3:套餐构造类,及详细套餐的Bulider
package com.xdnote.DesignPattern.creational.bulider;
public abstract class ComboBulider {
//每个套餐制造者们都有自己的套餐属性,按照套餐属性订做套餐
private Combo combo;
//给套餐加入套餐需要的内容
public abstract void builder();
//给套餐对应的套餐优惠
public abstract void disCount();
//开始制作套餐
public void bulidCombo(){
this.combo = new Combo();
this.builder();
}
//取套餐
public Combo getCombo(){
return this.combo;
}
//套餐公用的方便代码
public void addProduct(Product p){
this.combo.addProduct(p);
}
public void setDiscount(int discount){
this.combo.setDiscount(discount);
}
}
public class Combo1Bulider extends ComboBulider{
@Override
public void builder() {
this.addProduct(Product.PRODUCT1);
this.addProduct(Product.PRODUCT3);
}
@Override
public void disCount() {
this.setDiscount(5);
}
}
public class Combo2Bulider extends ComboBulider{
@Override
public void builder() {
this.addProduct(Product.PRODUCT1);
this.addProduct(Product.PRODUCT2);
this.addProduct(Product.PRODUCT3);
}
@Override
public void disCount() {
this.setDiscount(10);
}
代码4:接口类,与客户端打交道的,这里为Server
package com.xdnote.DesignPattern.creational.bulider;
/**
* Server在Buider充当角色: 服务员
* 和工厂一样:接收命令,再返回最终需要的实体对象
* 和工厂不一样:工厂收到命令就直接做菜了,而构造收到命令后 要再给工厂去做,
* 工厂就好比杂货商,买一个馒头我就给你一个馒头,买一个包子我就给你一个包子,客户直接和你的生产地打交道
* 而构造则是买一个馒头,则告诉做馒头的伙计去做一个馒头,做完了,再取走,再给客户,客户只和你的服务员打交道
* */
/**
* 作为服务员:应该有
* 接收客户的命令(被点餐)
* 去厂房拿货(去通知作餐)
* 把货给客户(取餐,取餐给用户之前要打折)
* */
/**
* 适用性,
* */
public class Server {
//呼叫服务员
private ComboBulider bulider ;
public Server(){}
//服务员要知道客户需要什么,然后实例化需要的套餐制作人员
public void setBuider(ComboBulider bulider){
this.bulider = bulider;
}
public Combo getCombo(){
//通知套餐制作人员制作套餐
this.bulider.bulidCombo();
//服务员要完成打打折,当然他不知道具体的折扣
this.bulider.disCount();
//打完折后取餐
return this.bulider.getCombo();
}
}
代码5:客户端调用
public static void main(String[] args) {
Server server = new Server();
server.setBuider(new Combo1Bulider());
Combo combo = server.getCombo();
System.out.println(combo);
Server server2 = new Server();
server2.setBuider(new Combo2Bulider());
Combo combo2 = server2.getCombo();
System.out.println(combo2);
}
小结
构造者模式 Builder
- 使用频率:
低
可能是由于Web项目结构简单,一般情况下很少用构造者模式去创建对象。
- 利弊影响:
低
利:对类型固定的对象很容易组合,理解此模式可以很好的理解面向对象思想。
弊:构造器模式其实只是实现了单产品与多产品对象的松耦合,灵活性上好像还不怎么样。
- 小评:
个人在Java中好像非常少的使用,相反在Javascript里面还使用过一些,虽然是函数式的语言,但也可以用面向对象的思维去写嘛。比如prototype什么的。