Skip to the content.
package com.bookshop.behavioral.templatemethod;

import com.bookshop.domain.Book;
import java.math.BigDecimal;
import java.util.List;

/**
 * The template: {@link #generate} fixes the report's skeleton -- header, one line
 * per sale, footer with the total -- and is {@code final} so no subclass can break
 * the sequence. Subclasses fill in only the format-specific steps.
 */
public abstract class SalesReport {

    public final String generate(List<Book> sales) {
        StringBuilder out = new StringBuilder();
        out.append(header());
        for (Book sale : sales) {
            out.append(line(sale));
        }
        BigDecimal total = sales.stream().map(Book::price).reduce(BigDecimal.ZERO, BigDecimal::add);
        out.append(footer(total));
        return out.toString();
    }

    protected abstract String header();

    protected abstract String line(Book sale);

    protected abstract String footer(BigDecimal total);
}

Raw file