← Back

Design Pizza Pricing System

Medium
Question

Design Pizza Pricing System

Implement the Low Level Design (LLD) of a pizza pricing system.

The system should support:

  • Initializing a new pizza
  • Adding toppings to it
  • Calculating the final price of the pizza

Your implementation should be extensible so that new pricing rules can be added later (for example: combos, promos, size-based discounts).

Use the Decorator Design Pattern.


Toppings Catalog

Each topping has a per-serving cost.

ToppingCost per serving
cheeseburst100
corn50
onion30
capsicum50
pineapple60
mushroom40

Business Rules

Cheeseburst Tax Uplift

Cheeseburst is considered unhealthy food and attracts more tax.

If at least one serving of cheeseburst is present:

  • Increase the pizza’s entire tax rate by +30% of its current value
  • This uplift happens only once

Example:

base tax = 10
uplift = 0.30 × 10 = 3
new tax = 13

Additional cheeseburst servings do not increase tax further.


Cheeseburst Volume Discount

Cheeseburst pricing rule:

  • First serving → 100
  • Each additional serving → 70

Example:

3 servings → 100 + 70 + 70 = 240

Health Constraint (Mutual Exclusion)

mushroom is considered healthy food.

It cannot be combined with cheeseburst.

Rules:

  • If cheeseburst already exists, mushroom cannot be added
  • If mushroom already exists, cheeseburst cannot be added

If violated:

addTopping() returns false
No state change occurs

Constructor

PizzaPricing(int basePrice, int taxPercentage, String size)

Constraints

100 ≤ basePrice ≤ 10000
basePrice is always a multiple of 100
0 ≤ taxPercentage ≤ 1000

Example interpretation:

taxPercentage = 1000
means tax = 1000% = 10 × base price

Example:

basePrice = 200
taxPercentage = 1000

tax = 1000/100 × 200 = 2000

final price = 200 + 2000 = 2200

Another example:

basePrice = 200
taxPercentage = 18

tax = 18/100 × 200 = 36

final price = 236

Size

size ∈ { small, medium, large }

All constructor inputs are guaranteed to be valid.


Methods

Add Topping

boolean addTopping(String topping, int servingsCount)
  • servingsCount is a valid positive integer
  • Returns true if topping is successfully applied
  • Returns false if any rule fails
  • On failure → no state change

Get Final Price

int getFinalPrice()
  • Returns final price
  • Uses Round Half Up rounding rule
  • Can be called any time

Pricing and Tax Model

Step 1 — Subtotal

Subtotal = basePrice + Σ(topping costs applied)

Step 2 — Taxable Base

Taxable Base = Subtotal

Step 3 — Tax Rate

Tax rate starts with the constructor supplied taxPercentage.

Rules may modify the tax rate (example: cheeseburst uplift).


Step 4 — Tax Amount

Tax Amount = (Tax Rate / 100) × Subtotal

Step 5 — Final Price

Final Price (pre-round) = Subtotal + Tax Amount

Rounding Rule

To convert the final price to integer:

(int)(x + 0.5)

Examples:

4.6  → 5
4.51 → 5
4.49 → 4
4.5  → 5

Worked Examples

Example A — Cheeseburst uplift + toppings

PizzaPricing p = new PizzaPricing(200, 10, "small");

p.addTopping("cheeseburst", 1);   // true
p.addTopping("onion", 2);         // true

int price = p.getFinalPrice();    // 407

Calculation

base = 200

toppings
cheeseburst = 100
onion = 2 × 30 = 60

toppings total = 160

subtotal = 200 + 160 = 360

Cheeseburst tax uplift:

tax = 10 → 13
tax amount = 13% of 360 = 46.8
final price = 360 + 46.8 = 406.8
rounded = 407

Example B — Mutual exclusion rule

PizzaPricing q = new PizzaPricing(350, 8, "medium");

q.addTopping("mushroom", 2);      // true
q.addTopping("cheeseburst", 1);   // false

int price = q.getFinalPrice();    // 464

Calculation

base = 350

toppings
mushroom = 2 × 40 = 80

subtotal = 350 + 80 = 430
tax = 8% of 430 = 34.4
final price = 430 + 34.4 = 464.4
rounded = 464
Solution

Solution: Design Pizza Pricing System

This question is testing Decorator Pattern + Rule extensibility. The key idea: every topping decorates the base pizza and modifies price/tax behavior.

I'll show a clean interview-quality C++ design that is extensible.


1️⃣ Design Overview

We separate concerns:

Core abstraction

Pizza
 ├── BasePizza
 └── ToppingDecorator
        ├── CheeseBurst
        ├── Onion
        ├── Corn
        ├── Capsicum
        ├── Pineapple
        └── Mushroom

Each topping wraps the pizza and modifies behavior.


2️⃣ Pizza Interface

class Pizza {
public:
    virtual double getSubtotal() = 0;
    virtual double getTaxRate() = 0;
    virtual ~Pizza() {}
};

3️⃣ Base Pizza

class BasePizza : public Pizza {
private:
    int basePrice;
    double taxRate;

public:
    BasePizza(int price, int tax) {
        basePrice = price;
        taxRate = tax;
    }

    double getSubtotal() override {
        return basePrice;
    }

    double getTaxRate() override {
        return taxRate;
    }

    void setTaxRate(double newRate) {
        taxRate = newRate;
    }
};

4️⃣ Decorator Base Class

class ToppingDecorator : public Pizza {
protected:
    Pizza* pizza;

public:
    ToppingDecorator(Pizza* p) {
        pizza = p;
    }
};

5️⃣ Cheeseburst Decorator

Handles:

  • volume discount
  • tax uplift
class CheeseBurst : public ToppingDecorator {

private:
    int servings;

public:
    CheeseBurst(Pizza* p, int s) : ToppingDecorator(p) {
        servings = s;
    }

    double getSubtotal() override {

        double cost = 100;

        if(servings > 1)
            cost += (servings - 1) * 70;

        return pizza->getSubtotal() + cost;
    }

    double getTaxRate() override {

        double rate = pizza->getTaxRate();

        return rate * 1.3; // +30%
    }
};

6️⃣ Simple Toppings

Example Onion:

class Onion : public ToppingDecorator {

private:
    int servings;

public:
    Onion(Pizza* p, int s) : ToppingDecorator(p) {
        servings = s;
    }

    double getSubtotal() override {
        return pizza->getSubtotal() + servings * 30;
    }

    double getTaxRate() override {
        return pizza->getTaxRate();
    }
};

Example Mushroom:

class Mushroom : public ToppingDecorator {

private:
    int servings;

public:
    Mushroom(Pizza* p, int s) : ToppingDecorator(p) {
        servings = s;
    }

    double getSubtotal() override {
        return pizza->getSubtotal() + servings * 40;
    }

    double getTaxRate() override {
        return pizza->getTaxRate();
    }
};

7️⃣ PizzaPricing Manager

This class enforces business rules.

class PizzaPricing {

private:
    Pizza* pizza;

    bool hasCheeseBurst = false;
    bool hasMushroom = false;

public:

    PizzaPricing(int basePrice, int tax, string size) {
        pizza = new BasePizza(basePrice, tax);
    }

    bool addTopping(string topping, int servings) {

        if(topping == "cheeseburst") {

            if(hasMushroom) return false;

            pizza = new CheeseBurst(pizza, servings);

            hasCheeseBurst = true;

            return true;
        }

        if(topping == "mushroom") {

            if(hasCheeseBurst) return false;

            pizza = new Mushroom(pizza, servings);

            hasMushroom = true;

            return true;
        }

        if(topping == "onion") {
            pizza = new Onion(pizza, servings);
            return true;
        }

        if(topping == "corn") {
            pizza = new Onion(pizza, servings); // similar structure
            return true;
        }

        if(topping == "capsicum") {
            pizza = new Onion(pizza, servings);
            return true;
        }

        if(topping == "pineapple") {
            pizza = new Onion(pizza, servings);
            return true;
        }

        return false;
    }

    int getFinalPrice() {

        double subtotal = pizza->getSubtotal();

        double taxRate = pizza->getTaxRate();

        double tax = subtotal * taxRate / 100.0;

        double finalPrice = subtotal + tax;

        return (int)(finalPrice + 0.5);
    }
};

8️⃣ Example Execution

PizzaPricing p(200, 10, "small");

p.addTopping("cheeseburst",1);
p.addTopping("onion",2);

cout << p.getFinalPrice();

Result:

407

9️⃣ Why This Design Is Good (Interview Answer)

Decorator Pattern

  • dynamically adds toppings
  • avoids subclass explosion like:
PizzaWithOnion
PizzaWithCheese
PizzaWithCheeseAndOnion
PizzaWithCheeseAndOnionAndCorn

Decorator avoids exponential combinations.


🔟 Easy to Extend

Add new rule:

Example Combo topping

class ComboDecorator : public ToppingDecorator

No changes required to existing pizza classes.


1️⃣1️⃣ Time Complexity

Operations:

OperationComplexity
addToppingO(1)
getFinalPriceO(number_of_toppings)

1️⃣2️⃣ Possible Interview Follow-ups

Common follow-ups:

1️⃣ Size multiplier

small 1x
medium 1.2x
large 1.5x

2️⃣ Promo rules

buy 2 onion get 1 free

3️⃣ Max topping cap

max 10 toppings