建造者模式

2022-12-01  本文已影响0人  慎独静思

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
它使用多个简单的对象一步一步构建成一个复杂的对象,复杂对象通常由各个部分的子对象用一定的算法构成,当各个部分可能经常变化,但组合它们的算法确相对稳定时可以考虑使用建造者模式。

建造者模式

上图中我们创建了一个复杂对象,复杂对象是由两个简单对象构成的,组成复杂对象的简单对象可能经常变化,但组合它们的算法,也就是Builder对象是相对稳定的,此时可以考虑使用建造者模式。

咱们还是用抽象工厂模式 中提到的早餐的例子来说明

interface Item {
    float getPrice();
}

interface Drinks extends Item {
    void drink();
}

class Soybean implements Drinks {

    @Override
    public void drink() {
        System.out.println("drink Soybean");
    }

    @Override
    public float getPrice() {
        return 1.5f;
    }
}

class Milk implements Drinks {

    @Override
    public void drink() {
        System.out.println("drink milk");
    }

    @Override
    public float getPrice() {
        return 2f;
    }
}

interface Pasta extends Item {
    void eat();
}

class YouTiao implements Pasta {

    @Override
    public void eat() {
        System.out.println("eat you tiao");
    }

    @Override
    public float getPrice() {
        return 1f;
    }
}

class Bread implements Pasta {

    @Override
    public void eat() {
        System.out.println("eat bread");
    }

    @Override
    public float getPrice() {
        return 2.5f;
    }
}

以上内容是我们创建的simple item

interface Meal {
    void orderItem(Item item);

    float getCost();
}

class Breakfast implements Meal {

    private List<Item> items = new ArrayList<>();

    @Override
    public void orderItem(Item item) {
        items.add(item);
    }

    @Override
    public float getCost() {
        float result = 0f;
        for (Item item: items) {
            result += item.getPrice();
        }
        return result;
    }
}

这是我们创建的早餐类,它是个复杂对象

interface MealBuilder {
    void startOrder();
    Meal getMeal();
}

class BreakfastBuilder implements MealBuilder {

    private Meal meal;

    @Override
    public void startOrder() {
        meal = new Breakfast();
    }

    public void orderSoybean(int count) {
        Objects.requireNonNull(meal);
        for (int i = 0; i < count; i++) {
            meal.orderItem(new Soybean());
        }
    }

    public void orderMilk(int count) {
        Objects.requireNonNull(meal);
        for (int i = 0; i < count; i++) {
            meal.orderItem(new Milk());
        }
    }

    public void orderYouTiao(int count) {
        Objects.requireNonNull(meal);
        for (int i = 0; i < count; i++) {
            meal.orderItem(new YouTiao());
        }
    }

    public void orderBread(int count) {
        Objects.requireNonNull(meal);
        for (int i = 0; i < count; i++) {
            meal.orderItem(new Bread());
        }
    }

    @Override
    public Meal getMeal() {
        return meal;
    }
}

这是我们创建的builder,它用来创建复杂对象。

        BreakfastBuilder mealBuilder = new BreakfastBuilder();
        mealBuilder.startOrder();
        mealBuilder.orderSoybean(2);
        mealBuilder.orderYouTiao(3);
        mealBuilder.orderBread(2);

        Meal meal = mealBuilder.getMeal();
        System.out.println("Price is " + meal.getCost());

这是客户端使用builder创建meal的过程,builder隐藏了创建复杂对象的细节,给客户提供了方便调用的接口。
标准的使用过程中还存在一个Director角色,用来构建建造者,此处未使用。

平时我们比较常用的是链式调用的建造者模式。

class Breakfast implements Meal {

    private List<Item> items = new ArrayList<>();

    public Breakfast(Builder builder) {
        items.addAll(builder.items);
    }

    @Override
    public void orderItem(Item item) {
        items.add(item);
    }

    @Override
    public float getCost() {
        float result = 0f;
        for (Item item : items) {
            result += item.getPrice();
        }
        return result;
    }

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

        public Builder orderSoybean(int count) {
            for (int i = 0; i < count; i++) {
                items.add(new Soybean());
            }

            return this;
        }

        public Builder orderMilk(int count) {
            for (int i = 0; i < count; i++) {
                items.add(new Milk());
            }

            return this;
        }

        public Builder orderYouTiao(int count) {
            for (int i = 0; i < count; i++) {
                items.add(new YouTiao());
            }

            return this;
        }

        public Builder orderBread(int count) {
            for (int i = 0; i < count; i++) {
                items.add(new Bread());
            }

            return this;
        }

        public Breakfast build() {
            return new Breakfast(this);
        }
    }
}

我们以链式调用的方式重写了上边的例子。

        Meal breakfast = new Breakfast.Builder()
                .orderSoybean(2)
                .orderBread(3)
                .orderYouTiao(2)
                .build();

        System.out.println("Price is: " + breakfast.getCost());

直观上来说,感觉链式调用的方式更容易理解和使用,可能是因为平时接触的最多的还是链式调用的构建者模式。

看了一遍又写了一遍,感觉还是一知半解,悲
可能脑海中有这个印象了吧,遇到问题可以朝这个方向考虑。
完结。

参考
《设计模式-可复用面向对象软件的基础》

上一篇下一篇

猜你喜欢

热点阅读