← 返回首页
设计模式基础教程(十一)
发表时间:2021-08-21 19:06:09
建造者模式

1.建造者模式

无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮、方向盘、发动机等各种部件。而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。根据中文翻译的不同,建造者模式又可以称为生成器模式。

建造者模式包含如下角色: - Builder:抽象建造者 - ConcreteBuilder:具体建造者 - Director:指挥者 - Product:产品角色

2.实例

建造者模式可以用于描述KFC如何创建套餐:套餐是一个复杂对象,它一般包含主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)等组成部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。

项目结构图如下:

定义抽象产品

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;
    }   
}

定义抽象建造者

public abstract class MealBuilder {
    protected Meal meal=new Meal();
    public abstract void buildFood();
    public abstract void buildDrink();
    public Meal getMeal(){
        return meal;
    }
}

定义两个套餐的具体建造者

//SubMealBuilderA.java
public class SubMealBuilderA extends MealBuilder {
    @Override
    public void buildFood() {
        meal.setFood("一个鸡腿汉堡");
    }
    @Override
    public void buildDrink() {
        meal.setDrink("一杯可乐");

    }
}
//SubMealBuilderB.java
public class SubMealBuilderB extends MealBuilder {
    @Override
    public void buildFood() {
        meal.setFood("一个鸡肉卷");
    }
    @Override
    public void buildDrink() {
        meal.setDrink("一杯果汁");
    }
}

创建指挥者(Waiter)

public class KFCWaiter {
    private MealBuilder mealBuilder;
    public void setMealBuilder(MealBuilder mealBuilder) {
        this.mealBuilder = mealBuilder;
    }
    public Meal construct(){
        this.mealBuilder.buildFood();
        this.mealBuilder.buildDrink();
        return this.mealBuilder.getMeal();
    }
}

XML解析工具类

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

public class XmlUtils {

    public static Object getBean(){
        DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
            Document doc=documentBuilder.parse(XmlUtils.class .getClassLoader().getResourceAsStream("config.xml"));

            String className=doc.getElementsByTagName("className").item(0).getTextContent();
            return Class.forName(className).newInstance();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }
}

配置文档

<?xml version="1.0"?>
<config>
    <!-- <className>com.simoniu.domain.SubMealBuilderA</className> -->
    <className>com.simoniu.domain.SubMealBuilderB</className>
</config>

测试类

public class TestBuilder01 {
    public static void main(String[] args) {
        //动态确定套餐种类
        MealBuilder mealBuilder=(MealBuilder) XmlUtils.getBean();
        //服务员是指挥者
        KFCWaiter kfcWaiter=new KFCWaiter();
        //服务员准备套餐
        kfcWaiter.setMealBuilder(mealBuilder);
        //客户获取套餐
        Meal meal=kfcWaiter.construct();
        System.out.println("套餐组成:");
        System.out.println(meal.getFood());
        System.out.println(meal.getDrink());
    }
}

运行结果:
套餐组成:
一个鸡肉卷
一杯果汁