4. Which design pattern is used in the following code?

#include <cassert>
#include <ostream>

class Function
{
public:
    virtual double value(const double &x) const = 0;
    virtual void dump(std::ostream &o) const = 0;

public:
    virtual ~Function() { }
};

class LinearFunction
    : public Function
{
public:
    LinearFunction(const double &k, const double &b)
        : m_k(k)
        , m_b(b)
    { }

public:
    double value(const double &x) const { return m_k * x + m_b; }
    void dump(std::ostream &o) const
    {
        o << "f(x) = " << m_k << " * x + " << m_b << std::endl;
    }

private:
    double m_k;
    double m_b;
};

class QuadraticFunction
    : public Function
{
public:
    QuadraticFunction(const double &a, const double &b, const double &c)
        : m_a(a)
        , m_b(b)
        , m_c(c)
    { }

public:
    double value(const double &x) const { return (m_a * x + m_b) * x + m_c; }
    void dump(std::ostream &o) const
    {
        o << "f(x) = " << m_a << " * x^2 + " << m_b << " * x + " << m_c;
        o << std::endl;
    }

private:
    double m_a;
    double m_b;
    double m_c;
};

class FunctionExtra
    : public Function
{
protected:
    FunctionExtra(const Function *f) : m_f(f) { assert(f != nullptr); }

public:
    double value(const double &x) const
    {
        assert(m_f != nullptr);
        return m_f->value(x);
    }

    void dump(std::ostream &o) const
    {
        assert(m_f != nullptr);
        m_f->dump(o);
    }

public:
    ~FunctionExtra() { delete m_f; }

private:
    const Function *m_f;
};

class FunctionDumpPoints
    : public FunctionExtra
{
public:
    FunctionDumpPoints(const Function *f, const double &l, const double &r,
                       const double &d)
        : FunctionExtra(f)
        , m_l(l)
        , m_r(r)
        , m_d(d)
    {
        assert(f != nullptr);
        assert(l <= r);
        assert(d > 0.0);
    }

public:
    void dump(std::ostream &o) const
    {
        FunctionExtra::dump(o);
        dump_range(o);
    }

private:
    void dump_range(std::ostream &o) const
    {
        assert(m_l <= m_r);
        assert(m_d > 0.0);

        double x = m_l, y = 0;
        for (; x <= m_r; x += m_d) {
            y = value(x);
            o << "(" << x << ", " << y << ")" << std::endl;
        }
    }

private:
    double m_l;
    double m_r;
    double m_d;
};

class FunctionZeroOutside
    : public FunctionExtra
{
public:
    FunctionZeroOutside(const Function *f, const double &l, const double &r)
        : FunctionExtra(f)
        , m_l(l)
        , m_r(r)
    {
        assert(f != nullptr);
        assert(l <= r);
    }

public:
    double value(const double &x) const
    {
        assert(m_l <= m_r);

        return (x < m_l || m_r < x) ? 0.0 : FunctionExtra::value(x);
    }

private:
    double m_l;
    double m_r;
};