Recall: observer pattern
<aside> 💡 Decorator Pattern
eg. Windowing system
start with a basic window - add scrollbar - add menu
want to choose these enhancements at runtime
</aside>
Componenet
ConcreteComponent
Decorators
eg. Window w/ scrollbar is a kind of window and has a ptr to the underlying plain window
Window w/ scrollbar & menu is a window, has a ptr to window w/ scrollbar, which has a ptr to window
eg. Pizza
class Pizza {
public:
virtual float price() const = 0;
virtual desc() const = 0;
virtual ~Pizza(){}
};
class CrustAndSource:public Pizza {
public:
float price() const override {return 5.99;}
string desc() const override {return "Pizza";}
};
class Decorator:public Pizza {
protected:
Pizza *component;
public:
Decorator(Pizza *p):component{p}{}
virtual ~Decorator() {delete component;}
};
class StuffedCrust:public Decorator {
public:
StuffedCrust(Pizza *p): Decorator{p}{}
float price() const override {return component->price() + 2.69;}
string desc() const override {return component->desc() + "with stuffed crust";}
};
class Topping:public Decorator {
string theTopping;
public:
...//exercise
};
Use:
Pizza *p1 = new CrustAndSource;
p1 = new Topping{p1, "cheese"};
p1 = new Topping{p1, "mushrooms"};
p1 = new StuffedCrust{p1};
cout << p1->desc() << ' '
<< p1->price() << endl;
delete p1;
check: 25-decorator
<aside> 💡 v[i] - ith element of v
v.at() - checked version of v[i]
Problem:
C’s solution: f’ns return a status code or sets the global variable error
<aside> 💡 Exception
C++’s solution - when an error condition arises,
But we can write handlers to catch errs & deal with them
<aside> 💡 vector<T>:: at throws an exn of type std::out.of.range when it fails
</aside>
</aside>
We can handle it as follows ↓
import <stdexcept>;
...
try {
cout << v.at(10000); // statements that many throw go in a try block
}
catch(out.of.range r) {
cerr << "Range error," << r.what() << endl;
}
Now consider:
void f() {// ↓ class ↓ what .what() will say
throw out.of.range {"f"};
}
void g() { f(); }
void h() { g(); }
int main() {
try { h(); }
catch(out.of.range) {...}
}
What happens?
main calls h
h calls g
g calls f
f throws out.of.range
Control goes back through the call chain (unwinding the stack) until a handler is found
No matching handler in the entire call chain → program teminates
A handler might do part of the recovery job, i.e. execute some corrective code & throw another exn