设计模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

介绍

  • 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
  • 主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
  • 何时使用:一些基本部件不会变,而其组合经常变化的时候
  • 如何解决:将变与不变分离开
  • 关键代码:
    • 建造者:创建和提供实例
    • 导演:管理建造出来的实例的依赖关系
  • 应用实例:
    1. 去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"
    2. JAVA 中的 StringBuilder
  • 优点:
    1. 建造者独立,易扩展
    2. 便于控制细节风险
  • 缺点:
    1. 产品必须有共同点,范围有限制
    2. 如内部变化复杂,会有很多的建造类
  • 使用场景:
    1. 需要生成的对象具有复杂的内部结构
    2. 需要生成的对象内部属性本身相互依赖
  • 注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序

实现

假设一个快餐店的案例:一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)

  • 汉堡: 可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中
  • 冷饮: 可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中

  • 思路

    1. 创建一个表示食物种类的 Item 接口和实体类
    2. 创建一个表示食物包装的 Packing 接口和实体类,汉堡是包在纸盒中,冷饮是装在瓶子中
    3. 创建一顿饭Meal的实体类,以及制造一顿饭的实现类MealBuilder(其实就是把不同的食物组合到一起构成一个Meal)
    4. 最后是测试类

1. 创建食物类型 和 食物包装的接口

/**
 * 食物种类接口
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public interface Item {
    
    /**
     * 名称
     * @return
     */
    public String name();
    
    /**
     * 价格
     * @return
     */
    public float price();
    
    /**
     * 包装
     * @return
     */
    public Packing packing();
}
/**
 * 食物包装接口
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public interface Packing {
    
    /**
     * 包装
     * @return
     */
    public String pack();
}

2. 创建包装接口的实现类

/**
 * 瓶子包装实体类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class Bottle implements Packing {

    @Override
    public String pack() {
        
        return "Bottle";
    }
}
/**
 * 纸盒包装实体类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class Wrapper implements Packing {

    @Override
    public String pack() {
        
        return "Wrapper";
    }
}

3. 创建食物种类接口的抽象类

因为食物的种类比较繁多,但每种食物均有共同的属性,所以抽出一层抽象类

/**
 * 汉堡食物抽象类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public abstract class Burger implements Item {
    
    /**
     * 价格
     * @return
     */
    @Override
    public abstract float price();
    
    /**
     * 包装
     * @return
     */
    @Override
    public Packing packing() {
        
        return new Wrapper();
    }
}
/**
 * 冷饮食物抽象类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public abstract class ColdDrink implements Item {
    
    /**
     * 价格
     * @return
     */
    @Override
    public abstract float price();
    
    /**
     * 包装
     * @return
     */
    @Override
    public Packing packing() {
        
        return new Bottle();
    }
}

4. 创建具体食物的实体类

/**
 * 素食汉堡食物实体类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class VegBurger extends Burger {

    @Override
    public String name() {
        
        return "Veg Burger";
    }

    @Override
    public float price() {
        
        return 10.0f;
    }
}
/**
 * 鸡肉汉堡食物实体类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class ChickenBurger extends Burger {

    @Override
    public String name() {
        
        return "Chicken Burger";
    }

    @Override
    public float price() {
        
        return 20.0f;
    }
}
/**
 * 可口可乐食物实体类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class Coke extends ColdDrink {

    @Override
    public String name() {
        
        return "Coke";
    }

    @Override
    public float price() {
        
        return 5.0f;
    }
}
/**
 * 百事可乐食物实体类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class Pepsi extends ColdDrink {

    @Override
    public String name() {
        
        return "Pepsi";
    }

    @Override
    public float price() {
        
        return 5.0f;
    }
}

5. 创建一顿饭的实体类

import java.util.ArrayList;
import java.util.List;

/**
 * 一顿饭 实体类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class Meal {
    
    private List<Item> listItems = new ArrayList<Item>();
    
    /**
     * 增加食物
     * @param item
     */
    public void addItem(Item item) {
        listItems.add(item);
    }
    
    /**
     * 获取这顿饭的价格
     * @return
     */
    public float getPrice() {
        
        float price = 0;
        
        for(Item item : listItems) {
            price += item.price();
        }
        
        return price;
    }
    
    /**
     * 查看这顿饭的内容
     */
    public void showItems() {
        for(Item item : listItems) {
            System.out.println("Item : "+item.name()+", "+item.packing().pack()+", "+item.price());
        }
    }
}

6. 制造一顿饭(其实就是把各种食物组合到一起)

/**
 * 建造一顿饭
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class MealBuilder {
    
    /**
     * 准备一顿素食餐
     * @return
     */
    public Meal prepareVegMeal() {
        
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        
        return meal;
    }
    
    /**
     * 准备一顿非素食餐
     * @return
     */
    public Meal prepareNonVegMeal() {
        
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        
        return meal;
    }
}

7. 建造者模式的测试类

/**
 * 建造者模式 测试类
 * @author remainsu
 * @version 1.0 2019-06-13
 */
public class Test {
    
    public static void main(String[] args) {
        
        MealBuilder mealBuilder = new MealBuilder();
        
        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("------Veg Meal------");
        vegMeal.showItems();
        System.out.println("Price : "+ vegMeal.getPrice());
        
        System.out.println();
        
        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("------Non Veg Meal------");
        nonVegMeal.showItems();
        System.out.println("Price : "+ nonVegMeal.getPrice());
    }
}

运行结果:

------Veg Meal------
Item : Veg Burger, Wrapper, 10.0
Item : Coke, Bottle, 5.0
Price : 15.0

------Non Veg Meal------
Item : Chicken Burger, Wrapper, 20.0
Item : Pepsi, Bottle, 5.0
Price : 25.0

参考

  1. https://www.runoob.com/design-pattern/builder-pattern.html
Souviens Toi Que Tu Vas Mourir !
原文地址:https://www.cnblogs.com/remainsu/p/she-ji-mo-shi--jian-zao-zhe-mo-shi.html