Java常用设计模式————建造者模式

引言

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

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

实现概要

建造者模式的实现并没有一个特别经典的套路,原因是在多数情况下复杂对象的构建往往千奇百怪。但为了更好的理解建造者模式使用的场景,我们假设如下的功能需要:

因为建造者模式就是为了构建复杂对象,为了更加贴近这一点,以午餐(Meal)作为最终要被构建的对象,我们假设:午餐中分为食物(Item)包装(Packing)—>食物包含汉堡(Burger)冷饮(ColdDrink)两种;汉堡鸡肉汉堡(ChickenBurger)蔬菜汉堡(VegBurger)之分;冷饮可口可乐(Coke)百事可乐(Pepsi)之分;包装又分为瓶装(Bottle)袋装(Wrapper)两种。

如果你看不懂上面的描述,或者已经准备关闭浏览器去做眼睛保健操,那么下面的结构图可能对你有所帮助:

实现过程

一、创建基础接口

创建食物接口及具体实现类,创建包装接口及具体包装类:

public interface Item {
    /** 食物名称*/
    String name();
    /** 包装*/
    Packing packing();
    /** 总价*/
    float price();
}
public abstract class Burger implements Item {

    @Override
    public Packing packing() {
        return new Wrapper();
    }
}
public class ChickenBurger extends Burger {

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

    @Override
    public float price() {
        return 50.5f;
    }
}
public class VegBurger extends Burger {

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

    @Override
    public float price() {
        return 25.0f;
    }
}
public abstract class ColdDrink implements Item {

    @Override
    public Packing packing() {
        return new Bottle();
    }
}
public class Coke extends ColdDrink {

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

    @Override
    public String name() {
        return "Pepsi";
    }
    
    @Override
    public float price() {
        return 35.0f;
    }
}
public interface Packing {
    String pack();
}
public class Bottle implements Packing {

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

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

二、创建目标类型

此例中,目标类型即午餐类(Meal)

public class Meal {
    private List<Item> items = new ArrayList<Item>();

    public Meal addAll(List<? extends Item> items) {
        this.items.addAll(items);
        return this;
    }

    public Double getSum() {
        return this.items.stream()
                         .collect(Collectors.summarizingDouble(Item::price))
                         .getSum();
    }
    
    public Double getAverage() {
        return this.items.stream()
                         .collect(Collectors.summarizingDouble(Item::price))
                         .getAverage();
    }

    public void showItems() {
        this.items.forEach(item -> {
            System.out.print("Item : " + item.name());
            System.out.print(", Packing : " + item.packing()
                                                  .pack());
            System.out.println(", Price : " + item.price());
        });
    }
}

三、创建建造者类

public class MealBuilder {

    public Meal prepareMeal(Item... items) {
        return new Meal().addAll(Arrays.asList(items));
    }
}

四、测试

public class BuilderPatternDemo {

    public static void main(String[] args) {
        MealBuilder mealBuilder = new MealBuilder();
        
        Meal vegMeal = mealBuilder.prepareMeal(new VegBurger(), new Coke());
        System.out.println("Veg Meal");
        vegMeal.showItems();
        System.out.println("Total Cost: " + vegMeal.getSum());

        Meal nonVegMeal = mealBuilder.prepareMeal(new ChickenBurger(), new Pepsi());
        System.out.println("\n\nNon-Veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost: " + nonVegMeal.getSum());
    }
}

执行结果:

总结

意图:建造者模式的用意就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示,例如本例中相同的创建午餐的方式,但使用不同的基础对象,最终得出不一样的套餐。

使用场景:一些基础部件不会变,而其组合经常变化的时候。主要解决软件系统中,有时候会面临“一个复杂对象”的创建工作,其通常由多个子对象用一定的算法构成。由于需求的变化,这个复杂对象的各个部件经常面临着剧烈的变化,但将它们组合在一起的算法相对稳定。

优点:建造者独立,易扩展;便于控制细节风险。

缺点:产品必须有共同点,范围有限制;内部变化复杂,会有很多建造类。

鸣谢

建造者模式

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页