0
\$\begingroup\$

I have implemented a very basic sandwich (sub) shop which a user can add extra toppings at an additional cost. The cost is calculated and the contents of the sandwich is outputted.

I am learning design patterns and the book I am learning from (Head First Design Patterns) is in Java, which I am not too familiar with, so I may be making some errors.

Sub.h

#ifndef SUB_H
#define SUB_H
//Class Sub: Abstract Base class. 
//Following the decorator pattern
#include <string>
#include <memory>
class Sub
{
 public:
 virtual double getCost() = 0;
 virtual std::string getToppings() = 0;
 virtual ~Sub() = 0;
};
class Plain: public Sub
{
 public:
 double getCost() override;
 std::string getToppings() override;
};
class ExtraCheese: public Sub
{
 public:
 ExtraCheese(std::shared_ptr<Sub> s) : sub(s) {}
 double getCost() override;
 std::string getToppings() override;
 private:
 std::shared_ptr<Sub> sub;
};
class ExtraMeat: public Sub
{
 public:
 ExtraMeat(std::shared_ptr<Sub> s) : sub(s) {}
 double getCost() override;
 std::string getToppings() override;
 private:
 std::shared_ptr<Sub> sub;
};
class ExtraSauce: public Sub
{
 public:
 ExtraSauce(std::shared_ptr<Sub> s) : sub(s) {}
 double getCost() override;
 std::string getToppings() override;
 private:
 std::shared_ptr<Sub> sub;
};
#endif

Sub.cpp

#include "Sub.h"
inline Sub::~Sub(){}
//class Plain : public Sub
double Plain::getCost() 
{
 return 3.75;
}
std::string Plain::getToppings()
{
 return "Basic Sub";
}
//class ExtraCheese : public Sub
double ExtraCheese::getCost()
{
 return sub->getCost() + 0.75;
}
std::string ExtraCheese::getToppings()
{
 return sub->getToppings() + ", Extra Cheese";
}
//class ExtraMeat : public Sub
double ExtraMeat::getCost()
{
 return sub->getCost() + 1.50;
}
std::string ExtraMeat::getToppings()
{
 return sub->getToppings() + ", Extra Meat";
}
//class ExtraSauce : public Sub
double ExtraSauce::getCost()
{
 return sub->getCost() + 0.15;
}
std::string ExtraSauce::getToppings()
{
 return sub->getToppings() + ", Extra Sauce";
}

main.cpp

#include <iostream>
#include <memory>
#include "Sub.h"
int main()
{
 std::shared_ptr<Sub> s(new Plain());
 s = std::make_shared<ExtraCheese>(s); 
 s = std::make_shared<ExtraMeat>(s);
 s = std::make_shared<ExtraSauce>(s);
 std::cout<<"COST: "<< s->getCost() <<std::endl;
 std::cout<<"Toppings: " << s->getToppings() <<std::endl;
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Nov 8, 2013 at 4:12
\$\endgroup\$
1
  • 3
    \$\begingroup\$ You should probably use int for monetary units. You don't want to have rounding errors. Use int and make the price in cent (you can put the decimal point in when printing). \$\endgroup\$ Commented Nov 8, 2013 at 5:49

1 Answer 1

4
\$\begingroup\$

No:

An object "Sub" and a decorator "Topping" implement the same interface. In addition a decorator takes an item (of the same interface) that it is decorating.
This is not quite what you have done.

What if I want extra cheese and meat?

You need something more like this:

class Price
{
 public:
 virtual ~Price() = 0;
 virtual int getPrice() = 0;
};
class Sub: public Price
{
 public:
 int getPrice() override {return 375;}
};
class ExtraCheese: public Price
{
 std::unique_ptr<Price> item
 public:
 ExtraCheese(std::unique_ptr<Price>&& item)
 : item(std::move(item))
 {}
 int getPrice() override {return item->getPrice() + 25;}
};
int main()
{
 std::unique_ptr<Price> sub(new Sub);
 std::unique_ptr<Price> subCheese(new ExtraCheese(sub));
 std::unique_ptr<Price> subCheeseMeat(new ExtraMeat(subCheese));
 std::cout << subCheeseMeat->getPrice();
}
answered Nov 8, 2013 at 5:39
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.