1.生成器模式概念
在《Head First Design Patterns》文中是这么介绍生成器模式的,“封装一个产品的构造过程,并允许按步骤构造”,感觉说得不是很清楚。而在网上查找相关资料是这么解释的,建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式。
2.生成器模式的作用
建造者模式(Builder Pattern)的作用是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。这句话还是需要结合例子来分析解释。
3.使用场景
需要生成的对象具有复杂的内部结构,而组成该对象的基本元素是不变的,改变的是基本元素的不同组合。经常被用来创建组合结构。
4.优点和缺点
优点
1、将一个复杂对象的创建过程封装起来。
2、允许对象通过多个步骤来创建,并且可以改变过程(这里和只有一个步骤的工厂模式不同)。
缺点
1、产品必须有共同点,范围有限制。
2、如内部变化复杂,会有很多的建造类。
5.例子解析
这里举的例子是《Head First Design Patterns》一文中提到关于假期计划。每个人的度假计划都不一样,例如天数和活动类型。也就是说每个人每天的计划都可能不一样,例如lgy要安排五一的三天假期。5月1日他要去定旅馆,买公园门票,去外面餐馆吃饭,5月2号定旅馆,买公园门票,还要溜冰等冰上的特殊活动以及外出用餐;5月3号买公园门票,定旅馆和进行竞技场特殊活动。
所以我们可以看出假期计划中变化的有天数和活动类型(这里的活动类型指的是定旅馆,买公园门票,用餐和特殊活动),可以看出一天的假期计划是通过某一天的日期与各种活动组合而成的。
上面的类图是《Head First Design Patterns》一文中给出的,我写的例子与上面给出的类图有些不一样。
首先我们看一下活动类型,ActivityType是活动类型的接口,所以的活动类型都实现了这个接口。
/**
* @author LGY
* 活动类型
*/
public interface ActivityType {
/**
* 活动名称
* @return
*/
public String actionName();
/**
* 预算
* @return
*/
public float actionCost();
}
活动类型:订房
public class BookingRooms implements ActivityType{
@Override
public String actionName() {
return "订房";
}
@Override
public float actionCost() {
return 260;
}
}
活动类型:公园买票
public class BuyingTickets implements ActivityType {
@Override
public String actionName() {
return "购买门票";
}
@Override
public float actionCost() {
return 500;
}
}
活动类型:用餐
public abstract class Dining implements ActivityType {
@Override
public String actionName() {
return "用餐";
}
public abstract float actionCost();
public abstract String dinningLocation();
}
去黄焖鸡用餐
public class HaveDinning1 extends Dining {
@Override
public String dinningLocation() {
return "黄焖鸡米饭";
}
@Override
public float actionCost() {
return 40;
}
@Override
public String actionName() {
return super.actionName() + dinningLocation();
}
}
去沙县小吃用餐
public class HaveDinning2 extends Dining{
@Override
public float actionCost() {
return 35;
}
@Override
public String dinningLocation() {
return "沙县小吃";
}
@Override
public String actionName() {
return super.actionName()+dinningLocation();
}
}
活动类型:特殊活动
public interface SpecialActivity extends ActivityType {
public String specificName();
}
特殊活动之冰上模式
public class TheIcePattern implements SpecialActivity {
@Override
public String actionName() {
return "特殊活动"+specificName();
}
@Override
public float actionCost() {
return 1000;
}
@Override
public String specificName() {
return "冰上模式";
}
}
特殊活动之竞技场模式
public class ArenaModel implements SpecialActivity {
@Override
public String actionName() {
return "特殊活动"+specificName();
}
@Override
public float actionCost() {
return 3000;
}
@Override
public String specificName() {
return "竞技场模式";
}
}
假期计划接口
/**
* @author LGY
* 假期计划
*/
public interface IVacationPlanBuilder {
public void addActivity(ActivityType activityType);
public void bulidDay(String date);
public String getVacationPlaner();
public void setVacationPlaner(String vacationPlaner);
public void print();
}
假期计划对象实例
public class VacationBuilder implements IVacationPlanBuilder{
private List<ActivityType> list = new ArrayList<ActivityType>();
private String date = null;
private String vacationPlaner = null;
public List<ActivityType> getActivityList() {
return list;
}
@Override
public void bulidDay(String date) {
this.date = date;
}
@Override
public String getVacationPlaner() {
return vacationPlaner;
}
@Override
public void setVacationPlaner(String vacationPlaner) {
this.vacationPlaner = vacationPlaner;
}
@Override
public void addActivity(ActivityType activityType) {
list.add(activityType);
}
public void print()
{
System.out.println("假期规划日:"+this.date);
System.out.println("假期规划人:"+this.vacationPlaner);
for (int i = 0; i < list.size(); i++) {
System.out.println("("+i+") "+list.get(i).actionName()+" 预算:"+list.get(i).actionCost());
}
}
}
客户端调用
public class Client {
public static void main(String[] args) {
IVacationPlanBuilder builder5_1 = new VacationBuilder();
builder5_1.setVacationPlaner("lgy");
builder5_1.bulidDay("2017年5月1日");
builder5_1.addActivity(new BookingRooms());
builder5_1.addActivity(new BuyingTickets());
builder5_1.addActivity(new HaveDinning1());
builder5_1.print();
IVacationPlanBuilder builder5_2 = new VacationBuilder();
builder5_2.setVacationPlaner("lgy");
builder5_2.bulidDay("2017年5月2日");
builder5_2.addActivity(new BookingRooms());
builder5_2.addActivity(new BuyingTickets());
builder5_2.addActivity(new TheIcePattern());
builder5_2.addActivity(new HaveDinning2());
builder5_2.print();
IVacationPlanBuilder builder5_3 = new VacationBuilder();
builder5_3.setVacationPlaner("lgy");
builder5_3.bulidDay("2017年5月3日");
builder5_3.addActivity(new BuyingTickets());
builder5_3.addActivity(new BookingRooms());
builder5_3.addActivity(new ArenaModel());
builder5_3.print();
}
}
// 输出结果:
// 假期规划日:2017年5月1日
// 假期规划人:lgy
// (0) 订房 预算:260.0
// (1) 购买门票 预算:500.0
// (2) 用餐黄焖鸡米饭 预算:40.0
// 假期规划日:2017年5月2日
// 假期规划人:lgy
// (0) 订房 预算:260.0
// (1) 购买门票 预算:500.0
// (2) 特殊活动冰上模式 预算:1000.0
// (3) 用餐沙县小吃 预算:35.0
// 假期规划日:2017年5月3日
// 假期规划人:lgy
// (0) 购买门票 预算:500.0
// (1) 订房 预算:260.0
// (2) 特殊活动竞技场模式 预算:3000.0
6.总结
“将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示",现在我们应该可以理解这句话的意思了,生成器模式主要用于创建一个由许多基础部分组合而成的对象,而通过这些基础部分的不同组合可以让这个对象拥有不同的表现。感觉《Head First Design Patterns》没有将生成器模式进行详细介绍也许是这个模式不经常使用到。
7.参考文章
http://www.runoob.com/design-pattern/builder-pattern.html