建造者模式(Builder Pattern):
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。(Separate the construction of a complex object from its representation so that the same construction process can create different representations.)
建造模式的本质:
应用场景:
建造者模式的优缺点:
优点:
缺点:
与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
Mybatis中用到的建造者模式:SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder等。
比如:XMLConfigBuilder读取配置文件构建出Configuration对象,然后SqlSessionFactoryBuilder使用Configuration对象作为参数,构建出SqlSessionFactory对象。
原因:这么做的原因是Mybatis的初始化工作较复杂,不是一个构造函数就能包括的。所以采用了分层构建方法。例如Mybatis中极其重要的Configuration对象,它庞大且复杂,初始化比较麻烦,所以使用专门的建造者XMLConfigBuilder进行构建。
实例:
比如:建造者模式可以用于描述KFC如何创建套餐:套餐是一个复杂对象,它一般包含主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)等组成部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。
整个过程大致可以分为5步:
第一,定义Product(产品角色): 一个具体的产品对象。
/**
* 一个具体的产品对象,实体
*/
public class Meal {
private String food;
private String drink;
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
第二,定义Builder(抽象建造者): 创建一个Product对象的各个部件指定的抽象接口。
/**
* 抽象建造者
*/
public abstract class MealBuilder {
Meal meal = new Meal();
public abstract void buildFood();
public abstract void buildDrink();
public Meal getMeal(){
return meal;
}
}
第三,定义ConcreteBuilder(具体建造者): 实现抽象接口,构建和装配各个部件。
/**
* 具体建造者:A套餐
*/
public class MealA extends MealBuilder{
public void buildDrink() {
meal.setDrink("可乐");
}
public void buildFood() {
meal.setFood("薯条");
}
}
/**
* 具体建造者:B套餐
*/
public class MealB extends MealBuilder{
public void buildDrink() {
meal.setDrink("柠檬果汁");
}
public void buildFood() {
meal.setFood("鸡翅");
}
}
第四,定义Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
/**
* 指挥者:构建一个使用Builder接口的对象
*/
public class KFCServer {
private MealBuilder mealBuilder;
public KFCServer(MealBuilder mealBuilder) { //构造方法
this.mealBuilder = mealBuilder;
}
public Meal construct(){
//准备食物
mealBuilder.buildFood();
//准备饮料
mealBuilder.buildDrink();
//准备完毕,返回一个完整的套餐给客户
return mealBuilder.getMeal();
}
}
第五,定义测试类:
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
MealA a = new MealA();//创建套餐A对象
KFCServer waitera = new KFCServer(a);//准备套餐A的服务员
Meal mealA = waitera.construct();//获得套餐A
System.out.print("套餐A的组成部分:");
System.out.println("食物:"+mealA.getFood()+"; "+"饮品:"+mealA.getDrink());
MealB b = new MealB();
KFCServer waiterb = new KFCServer(b);
Meal mealB = waiterb.construct();
System.out.print("套餐B的组成部分:");
System.out.println("食物:"+mealB.getFood()+"; "+"饮品:"+mealB.getDrink());
}
}
如果想了解更多设计模式,可点击:设计模式概述 以及 23种设计模式的介绍