【设计模式学习笔记】4:认识建造者模式与StringBuilder

简述

建造者模式有点像工厂模式,不过工厂模式对外并不展现产品的制造过程,建造者模式却是将产品的装配方法暴露给了使用者,使用者可以通过自行调用这些装配方法、策划调用的次序,来在一定程度上影响产品的制造结果。

Runoob上给出了一个在KFC点餐的例子,即用户可以点汉堡、薯条、鸡翅等,但是点这些餐品的顺序不同,所生成的产品(倒不如说是副产品)——订单条也就不太一样。

程序

我将这个过程简化成了一个比Runoob上更清晰的程序。

SnacksBuilder接口

package org.lzh.builder;

import org.lzh.enumeration.Size;

//小吃的建造者接口
public interface SnacksBuilder {
    void buildFrenchFries(Size size);//加个薯条
    void buildCoke(Size size);//加个可乐
}

StapleBuilder接口

package org.lzh.builder;

import org.lzh.enumeration.Taste;

//主食的建造者接口
public interface StapleBuilder {
    void buildHamburger(Taste taste);//加个汉堡
    void buildChickenRoll();//加个鸡肉卷
}

KFCBuilder建造者类

package org.lzh.builder.imp;

import org.lzh.builder.SnacksBuilder;
import org.lzh.builder.StapleBuilder;
import org.lzh.enumeration.Size;
import org.lzh.enumeration.Taste;

import java.util.LinkedList;
import java.util.List;

//模拟KFC点餐的建造者实体类,可以点主食和小吃
public class KFCBuilder implements StapleBuilder, SnacksBuilder {
    //订单
    private List<String> order = new LinkedList<>();

    @Override
    public void buildFrenchFries(Size size) {
        order.add((size == Size.LARGE ? "大" : size == Size.MID ? "中" : "小") + "薯条");
    }

    @Override
    public void buildCoke(Size size) {
        order.add((size == Size.LARGE ? "大" : size == Size.MID ? "中" : "小") + "杯可乐");
    }

    @Override
    public void buildHamburger(Taste taste) {
        order.add((taste == Taste.SPICY ? "香辣" : "劲脆") + "鸡腿堡");
    }

    @Override
    public void buildChickenRoll() {
        order.add("老北京鸡肉卷");
    }

    //获取订单
    public List<String> getOrder() {
        return order;
    }

    //展示订单
    public void showOrder() {
        for (String s : this.order) {
            System.out.println("|---" + s);
        }
    }
}

Main场景类

package org.lzh;

import org.lzh.builder.imp.KFCBuilder;
import org.lzh.enumeration.Size;
import org.lzh.enumeration.Taste;

public class Main {
    public static void main(String[] args) {
        KFCBuilder kfcBuilder = new KFCBuilder();
        kfcBuilder.buildChickenRoll();
        kfcBuilder.buildCoke(Size.LITTLE);
        kfcBuilder.buildFrenchFries(Size.LARGE);
        kfcBuilder.buildHamburger(Taste.NOTSPICY);
        kfcBuilder.showOrder();
    }
}

运行结果

|---老北京鸡肉卷
|---小杯可乐
|---大薯条
|---劲脆鸡腿堡

StringBuilder

StringBuilder是字符串的一个建造者类,我认为它是说明建造者模式的一个绝佳的例子。它继承了一个抽象的建造者类,并像String一样用final修饰不允许被继承:

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

在抽象的AbstractStringBuilder类中,可以看到很多和建造字符串有关的方法,如:

public void setCharAt(int index, char ch){
    //...
}

public AbstractStringBuilder append(/*各种类型的参数*/){
    //...
}

public AbstractStringBuilder delete(int start, int end){
    //...
}

public AbstractStringBuilder deleteCharAt(int index){
    //...
}

public AbstractStringBuilder replace(int start, int end, String str){
    //...
}

//还有很多...

其中以AbstractStringBuilder为返回值的方法,皆尽返回this,可见它们都是用来建造字符串的方法,并且可以方便地做链式调用。StringBuilder维护了一个缓冲区,使用者通过组合这些方法,并传递不同的参数,就可以用来构建各式各样的字符串了,这正是使用了建造者模式。

这个类的存在让字符串的构造更加灵活。在这里,最终生成的各式各样的字符串就是产品,而这些产品的建造过程是可以抽象成几种步骤的,通过这些步骤的组合能更灵活方便地建造这些产品,这就是建造者模式的使用情景——定制化。

猜你喜欢

转载自blog.csdn.net/SHU15121856/article/details/81488969