- 生成器模式
生成器模式是一种对象的创建模式,可以将一个复杂产品的内部表象和产品的生产过程分隔开来,(构建与表示分离)。使得同样的构建过程可以创建不同的表示。
简单的来说,就是讲一个复杂的对象拆分成一个一个小的对象,然后通过排列组合的方式生成不同的复杂对象。举个栗子:例如快餐店的套餐,会有个定价,比如说总价是20元套餐。可以有两素菜一个荤菜。素菜包括清炒白菜、土豆丝、麻婆豆腐等等,荤菜包括口水鸡,啤酒鸭,小炒肉等等。这样只要是两素菜一荤菜组合,就能形成一个个套餐。这其实就类似于生成器模式。这里的复杂产品是套餐,而生产过程则是一个一个的小菜。 - 生成器模式示意图
3.生成器模式所含角色
- 产品角色: 产品是要构建的复杂对象。
- 抽象建造者角色: 为创建产品角色对象的各个部分指定抽象接口,一般至少包含有两个方法,一个是建造产品,一个是返回产品。
- 具体建造者角色: 实现抽象建造者角色。并且根据不同的情形对于产品创建给出具体的方法。并且能够在创建完成后返回产品实例。
- 导演角色: 构造一个能够使用抽象建造者的对象。该角色不涉及具体的产品信息。主要负责和客户端打交道。
- 示例代码:
场景:某旅游网站推出了3日游和4日游的业务。需要设计一个度假计划生成的项目。
产品角色:
public class Vacation {
private Date date;
private ArrayList<VacationDay> vacationDays=null;
private int days = 0;
private VacationDay vacationDay;
public Vacation(String dt) {
vacationDays = new ArrayList<VacationDay>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
date = sdf.parse(dt);
vacationDay = new VacationDay(date);
vacationDays.add(vacationDay);
days++;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void setDate(String dt){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
date = sdf.parse(dt);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Date getDate() {
return date;
}
/**
* 获取下一天
* @param n
* @return
*/
private Date nextDate(int n){
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE, n);
return cal.getTime();
}
/**
* 假期中的下一天
*/
public void addDay(){
vacationDay = new VacationDay(nextDate(days));
vacationDays.add(vacationDay);
days++;
}
public boolean setVacationDay(int i){
if ((i > 0) && (i < vacationDays.size())) {
vacationDay = vacationDays.get(i);
return true;
}
vacationDay = null;
return false;
}
public void setHotel(String hotel){
vacationDay.setHotel(hotel);
}
public void setEvent(String event){
vacationDay.addEvents(event);
}
public void setTicket(String ticket){
vacationDay.addtickets(ticket);
}
public void showInfo() {
for (int i = 0, len = vacationDays.size(); i < len; i++) {
System.out.println("** " + (i + 1) + " day**");
System.out.println(vacationDays.get(i).toString());
}
}
}
假期中的每天用一个具体类标示:
public class VacationDay {
private Date date;
private String hotel;
private ArrayList<String> events;
private ArrayList<String> tickets;
public VacationDay(Date dt) {
date = dt;
events = new ArrayList<String>();
tickets = new ArrayList<String>();
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getHotel() {
return hotel;
}
public void setHotel(String hotel) {
this.hotel = hotel;
}
public void addEvents(String event){
events.add(event);
}
public void addtickets(String ticket){
tickets.add(ticket);
}
@Override
public String toString() {
return date + "VacationDay>>>>" +
"date=" + date +
", hotel='" + hotel + '\'' +
", events=" + events +
", tickets=" + tickets ;
}
}
抽象建造者角色:
public interface Builder {
void buildvacation();
void buildDay(int i);
void addHotel(String hotel);
void addTicket(String ticket);
void addEvent(String event);
Vacation getVacation();
}
具体建造者角色:
public class FourDaysBuilder implements Builder {
private Vacation vacation;
public FourDaysBuilder(String date) {
vacation = new Vacation(date);
}
/**
* 创建完整的假期的方法
*/
@Override
public void buildvacation() {
addTicket("机票");
addHotel("如家");
addEvent("住宿");
addEvent("晚餐");
vacation.addDay();;
addTicket("公园门票");
addEvent("游城市公园");
addTicket("水族馆门票");
addEvent("游水族馆");
addHotel("希尔顿酒店");
vacation.addDay();
addEvent("中央公园");
addTicket("观光bus");
addHotel("万达酒店");
vacation.addDay();
addTicket("机票");
addEvent("回家");
}
@Override
public void buildDay(int i) {
vacation.setVacationDay(i);
}
@Override
public void addHotel(String hotel) {
vacation.setHotel(hotel);
}
@Override
public void addTicket(String ticket) {
vacation.setTicket(ticket);
}
@Override
public void addEvent(String event) {
vacation.setEvent(event);
}
@Override
public Vacation getVacation() {
return vacation;
}
}
导演角色:
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void setBuilder(Builder builder) {
this.builder = builder;
}
public void construct(){
builder.buildvacation();
builder.getVacation().showInfo();
}
}
测试主函数:
public class Main {
public static void main(String[] args) {
Director director = new Director(new FourDaysBuilder("2019-01-30"));
director.construct();
}
}
- 生成器模式的总结:
从上面的实例代码看出,生成器模式的有点是建造者是独立的,便于扩展。但是缺点也很明显如果内部系统较为复杂就会有很多的建造类。生成器模式的使用是系统中的子系统具有相互的联系。