zl程序教程

您现在的位置是:首页 >  后端

当前栏目

设计模式——建造者模式

2023-09-27 14:25:21 时间

介绍

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。一个Buider类会一步一步的构建最终的对象,该Builder类是独立于其他对象的。

何时使用

一些基本的部件不变,而其组合经常变化的时候

如何解决

将变与不变分离开

应用实例

麦当劳里的汉堡、可乐、薯条、炸鸡等是不变的,但其组合经常变动,生成所谓的“套餐”

注意

与工厂模式相比,更加关注与零件装配的顺序

案例

快餐店案例,其中一个典型的套餐可是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chiken Burer),他们装在纸盒里;冷饮可以是可口可乐(coke)或百事可乐(pepsi),他们装在瓶子里。

我们创建一个表示食物条目(比如汉堡和冷饮)的Item接口和实现Item接口的实体类,以及一个表示食物包装的Packing接口和实现Packing接口的实体类。汉堡包在纸盒里,可乐装在瓶子里。

然后我们创建一个Meal类,带有Item的ArrayList和一个通过Item来创建不同类型的Meal对象的MealBuilder。
步骤一

创建一个表示食物条目和食物包装的接口

Item.java

public interface Item {
    public String name();
    public Packing packing();
    public float price();
}

Packing.java

public interface Packing {
    public String pack();
}

步骤二

实现Packing接口的实体类

Wrapper.java

public class Wrapper implements Packing{
    public String pack() {
        return "Wrapper";
    }
}

Bottle.java

public class Bottle implements Packing{
    public String pack() {
        return "Bottle";
    }
}

步骤三

实现Item接口的抽象类,该类提供默认的功能

Burger.java

public abstract class Burger implements Item {
    public Packing packing(){
        return new Wrapper();
    }
    public abstract float price();
}

ColdDrink.java

public abstract class ColdDrink implements Item{
    public Packing packing(){
        return new Bottle();
    }
    public abstract float price();
}

步骤四

创建扩展了Burger和ColdDrink的实体类

VegBurger.java

public class VegBurger extends Burger{
    public float price(){
        return 25.0f;
    }
    public String name(){
        return "Veg Burger";
    }
}

ChickBurger.java

public class ChikenBurger extends Burger{
    public float price(){
        return 50.5f;
    }
    public String name(){
        return "Chicken Burger";
    }
}

Cock.java

public class Coke extends ColdDrink{
    public float price(){
        return 30.0f;
    }
    public String name(){
        return "Coke";
    }
}

Pepsi.java

public class Pepsi extends ColdDrink{
    public float price(){
        return 35.0f;
    }
    public String name(){
        return "Pepsi";
    }
}

步骤五

创建一个Meal类,带有上面定义的Item对象

Meal.java

import java.util.List;
import java.util.ArrayList;
public class Meal {
    private List<Item> items = new ArrayList<Item>();
    public void addItem(Item item){
        items.add(item);
    }
    public float getCost(){
        float cost = 0.0f;
        for (Item item: items){
            cost += item.price();
        }
        return cost;
    }
    public void showItems(){
        for (Item item: items){
            System.out.println("Item:" + item.name());
            System.out.println(", Packing:" + item.packing().pack());
            System.out.println(", Price:" + item.price());
        }
    }
}

步骤六

创建一个MealBuilder类,实际上builder类负责创建Meal对象,下面创建了2份套餐

MealBuilder.java

public class MealBuilder {
    public Meal prepareVegMeal(){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }

    public Meal prepareNonVegMeal(){
        Meal meal = new Meal();
        meal.addItem(new ChikenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}

步骤七

演示创建者模式

BuilderPatternDemo.java

public class BuilderPatternDeom {
    public static void main(String []args){
        MealBuilder mealBuilder = new MealBuilder();

        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("veg Meal");
        vegMeal.showItems();
        System.out.println("Total Cost:" + vegMeal.getCost());

        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("mon veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost:" + nonVegMeal.getCost());
    }
}

步骤八

输出

veg Meal
Item:Veg Burger
, Packing:Wrapper
, Price:25.0
Item:Coke
, Packing:Bottle
, Price:30.0
Total Cost:55.0
Disconnected from the target VM, address: '127.0.0.1:63309', transport: 'socket'
mon veg Meal
Item:Chicken Burger
, Packing:Wrapper
, Price:50.5
Item:Pepsi
, Packing:Bottle
, Price:35.0
Total Cost:85.5