如果我们要出去旅游都需要制定旅游计划,包括旅游天数、定酒店等等,如果这时候你去专业的公司去定制你的旅游行程。这时候公司就如同一个生成器,根据游客需求定制一个合适的计划。我们发现旅游计划中有公共部分,那么我们设计一个大类,把所有可能会在计划中的项目都在这大类中构造创建方法。同时这个大类应该传入一个旅游计划对象,用于存储这个旅游计划。那么相对应的旅游计划类,则是一个标准的JavaBean,拥有setter和getter方法。然后客户类会建立一个方法,在这个方法中根据需求,调用相应的生成类中方法,将创建过程给封装了。这就是生成器模式,使用使用生成器模式封装一个产品的构造过程,并允许按步骤构造。
1.适用性和优缺点
1.适用性
a.当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
b.当构造过程必须允许被构造的对象有不同的表示。如同上面的被构造对象是旅游计划,而旅游计划可以有不同的。
2.优点
a.将一个复杂对象的过程封装起来。
b.允许对象通过多个步骤来创建并且可以改变过程(这和只有一个步骤的工厂模式不同)。
c.向客户隐藏产品内部的表现。
d.产品的实现可以被替换,客户只看到一个抽象接口。
3.缺点
与工厂模式相比,采用生成器模式创建对象的客户,需要具备更多领域的知识。
2.示例讲解
本文就将一个旅游计划的例子,通过封装旅游计划制定的过程来实现目标。首先有一个完整的计划类,即所有计划项目都包括其中,然后有一个表示创建过程的类,然后生成器类负责封装制作过程,客户类只需要调用相应的生成方法即可。
首先是builder接口,定义一个创建产品过程的接口
package builderpattern;
public interface Builder {
void buildDay(int day);
void addHotel(String hotel);
void addTickets(String tickets);
void addDestination(String destination);
Planner getVacationPlanner();
}
然后是该接口的实现,这里是旅游计划创建过程的实现。
package builderpattern;
public class VacationBuilder implements Builder {
Planner pl;
public VacationBuilder()
{
pl=new VacationPlanner();//建立一个VacationPlanner对象
}
@Override
public void buildDay(int day) {
// TODO Auto-generated method stub
pl.setDay(day);
}
@Override
public void addHotel(String hotel) {
// TODO Auto-generated method stub
pl.setHotel(hotel);
}
@Override
public void addTickets(String tickets) {
// TODO Auto-generated method stub
pl.setTickets(tickets);
}
@Override
public void addDestination(String destination) {
// TODO Auto-generated method stub
pl.setDestination(destination);
}
@Override
public Planner getVacationPlanner() {
// TODO Auto-generated method stub
return this.pl;
}
}
对应的是旅游计划对象,那么应该创建一个旅游计划类
package builderpattern;
public class Planner {
int day;//天数
String hotel;//旅馆
String tickets;//门票
String destination;//目的地
public void setDay(int day)
{
this.day=day;
}
public int getDay()
{
return this.day;
}
public void setHotel(String hotel)
{
this.hotel=hotel;
}
public String getHotel()
{
return this.hotel;
}
public void setTickets(String tickets)
{
this.tickets=tickets;
}
public String getTickets()
{
return this.tickets;
}
public void setDestination(String destination)
{
this.destination=destination;
}
public String getDestination()
{
return this.destination;
}
}
接着是client类,这里是构造一个使用builder对象的类,并通过内部方法封装builder对象的方法。
package builderpattern;
public class Client {
public Planner constructPlanner(int day,String hotel,String tickets,String destination,Builder builder) {
// TODO Auto-generated method stub
builder.buildDay(day);
builder.addHotel(hotel);
builder.addTickets(tickets);
builder.addDestination(destination);
return builder.getVacationPlanner();
}
}
最后,则是客户获得该自身的旅游计划。
package builderpattern;
public class Test {
private static void showPlanner(Planner pl)
{
if(pl.getDay()!=0)
System.out.println("旅游天数为"+pl.getDay()+"天");
if(pl.getHotel()!=null)
System.out.println("酒店定在"+pl.getHotel());
if(pl.getTickets()!=null)
System.out.println("买的门票是:"+pl.getTickets());
if(pl.getDestination()!=null)
System.out.println("旅游的目的地是:"+pl.getDestination());
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Builder builder=new VacationBuilder();
Client c1=new Client();
Planner pl1=c1.constructPlanner(10,null,"Gugong","Beijing",builder);
System.out.println("您好,这里是旅游服务,我们会根据您的需求为您打造完美的旅游计划!");
System.out.println("第一位游客的安排:");
showPlanner(pl1);
System.out.println("------------------");
Client c2=new Client();
Planner pl2=c2.constructPlanner(5,"Hilton","Disneland tickets","L.A",builder);
System.out.println("第二位游客的安排:");
showPlanner(pl2);
}
}
获得结果如下:
您好,这里是旅游服务,我们会根据您的需求为您打造完美的旅游计划!
第一位游客的安排:
旅游天数为10天
买的门票是:Gugong
旅游的目的地是:Beijing
------------------
第二位游客的安排:
旅游天数为5天
酒店定在Hilton
买的门票是:Disneland tickets
旅游的目的地是:L.A
从上面示例可以看出,生成器模式的核心在于,生成器负责封装一个产品复杂的创建过程。而且产品创建将一类产品的创建步骤一般化,针对具体产品则调用相应的具体过程即可。这也是它与工厂模式的区别,工厂模式是直接创建一个对象,而生成器模式将创建过程细化到每一个步骤。