Obiekt Logger odpowiada za przesłanie komunikatów, użytkownik woła metodę msg przekazując treść komunikatu. Treść ta jest zapisywana do odpowiednich miejsc, w zależności od konfiguracji. Przedstawione poniżej rozwiązanie ma pewne ograniczenia: (1) klasa jest zależna jest od wszystkich klas reprezentujących odbiorców komunikatu (Mail, File, cerr), (2) konfiguracja odbiorców komunikatów jest ogrniczona, na przykład nie można zapisywać do więcej niż trzech plików, nie można wyłączyć wysyłania komunikatów na strumień cerr ('cerr' obiekt reprezentujący standardowy strumień znakowy błędów).

//Klasa pomocnicza, jej nie zmieniamy
class File {
public:
	File(const std::string& file_name);
	void write(const std::string& msg);
};

//Klasa pomocnicza, jej nie zmieniamy
class Mail {
public:
	Mail(const std::string& address) {}
	void send(const std::string& msg) {}
};

class Logger {
public:
	Logger() : file1(nullptr), file2(nullptr), mail(nullptr) {}

	void setFile1(File* f) { file1 = f; }
	void setFile2(File* f) { file2 = f; }
	void setMail(Mail* e) { mail = e; }

	int msg(const string& msg) {
	    std::cerr << msg << std::endl;
		if(file1)
			file1->write(msg);
		if(file2)
			file2->write(msg);
		if(mail)
			mail->send(msg);
	}
private:
	File* file1;
	File* file2;
	Mail* mail;
};

Proszę odpowiedz na poniższe pytania:

  1. Popraw kod klasy Logger, aby zlikwidować wady (1) i (2). Skopiuj kod klasy Logger zmodyfikuj go, jeżeli jest to potrzebne. Możesz dodać nowe klasy, jeżeli jest to potrzebne. Twój kod nie musi się kompilować, ale powinno w nim być widać rozwiązanie.
  2. Czy zastosowałeś jakiś obiektowy wzorzec projektowy (tak/nie)? Jeżeli tak, napisz jego nazwę.

Rozwiązanie:
class Observer {
public:
	virtual void notify(const string& msg) = 0;
};

class FileObs : public Observer {
public:
	FileObs(const string& file_name) : f_(file_name) {}
	virtual void notify(const string& msg) { f_.write(msg); }
private:
	File f_;
};

class MailObs : public Observer {
public:
	MailObs(const string& address) : m_(address) {}
	virtual void notify(const string& msg) { m_.send(msg); }
private:
	Mail m_;
};

class StreamObs : public Observer {
public:
    StreamObs(const std::ostream& os) : os_(os) {}
	virtual void notify(const string& msg) { os << msg << std::endl; }
};

class LoggerBetter {
public:
	typedef vector Observers;

	LoggerBetter() {}

	void reg(Observer* o) { obs_.push_back(o); }

	int msg(const string& msg) const {
		for(Observers::const_iterator it = obs_.begin(); it != obs_.end(); ++it )
			(*it)->notify(msg);
	}
private:
	Observers obs_;
};
Przykład użycia
LoggerBetter logger_better;
FileObs obs_file1("file1");
FileObs obs_file2("file2");
MailObs obs_mail("address");
SteramObs obs_cerr(std::cerr);

logger_better.reg(&obs_file1);
logger_better.reg(&obs_file2);
logger_better.reg(&obs_mail);
logger_better.reg(&obs_cerr);
logger_better.msg("test");