My attempt at a observer design pattern (I know using namespace std isn't good). I'm very new to design patterns. Everything is inline with class definition. Please tell me if I'm doing anything wrong or if there is anything that can be improved. Does subscriber (observer) need to store info from update function? Also, is operator== ok for comparing and finding correct subscriber with name or should I use getname()?
Base:
class Subscriber
{
string name;
public:
Subscriber(string name) : name(name) {}
virtual void update(string title, double price) = 0;
string getname() const {return name;}
bool operator==(string name) {
if (this->name == name)
return true;
return false;
}
virtual ~Subscriber() {};
};
Derived:
class PaidSubscriber : public Subscriber
{
public:
PaidSubscriber(string name) : Subscriber(name) {}
void update(string title, double price) {
cout << "\nPaid Subscriber: " << getname() << endl;
cout << "New Issue: " << title << endl;
if (price > 0)
cout << "Price: $" << std::fixed << setprecision(2) << price << endl;
else
cout << "Price: FREE";
};
};
class VIPSubscriber : public Subscriber
{
public:
VIPSubscriber(string name) : Subscriber(name) {}
void update(string title, double price) {
cout << "\nVIP Subscriber: " << getname() << endl;
cout << "New Issue: " << title << endl;
if (price-10 > 0)
cout << "Price: $" << std::fixed << setprecision(2) << price-10 << endl;
else
cout << "Price: FREE";
};
};
class FreeSubscriber : public Subscriber
{
public:
FreeSubscriber(string name) : Subscriber(name) {}
void update(string title, double price) {
cout << "\nFree Subscriber: " << getname() << endl;
cout << "New Issue: " << title;
if (price > 0) {
cout << " (preview only)" << endl;
cout << "Upgrade to Paid Subscriber!" << endl;
}
else
cout << endl;
};
};
Subject:
class Magazine
{
string currissue;
double currprice;
list<Subscriber*>sublist;
public:
enum SubscriberType {SUB_FREE, SUB_PAID, SUB_VIP};
Magazine(string currissue, double currprice) : currissue(currissue), currprice(currprice) {}
void subscribe(string name, SubscriberType subtype) {
Subscriber *sub;
switch(subtype) {
case SUB_FREE:
sub = new FreeSubscriber(name);
break;
case SUB_PAID:
sub = new PaidSubscriber(name);
break;
case SUB_VIP:
sub = new VIPSubscriber(name);
break;
default:
return;
}
sublist.push_back(sub);
}
void unsubscribe(string name)
{
for (auto it = sublist.begin(); it != sublist.end(); it++) {
if (**it == name) {
sublist.erase(it);
break;
}
}
}
void changeissue(string name, double price) {
this->currissue = name;
this->currprice = price;
}
void notify()
{
for (auto sub : sublist)
sub->update(currissue, currprice);
}
~Magazine() {
for (auto sub : sublist)
delete sub;
}
};
Main:
int main()
{
Magazine nationalgeographic("Lions", 5.34);
nationalgeographic.subscribe("Ivy Parks", Magazine::SUB_PAID);
nationalgeographic.subscribe("Mike Gopher", Magazine::SUB_FREE);
nationalgeographic.subscribe("Stan Shunpike", Magazine::SUB_VIP);
nationalgeographic.notify();
nationalgeographic.changeissue("Elephants", 15.23);
nationalgeographic.notify();
}