/*************************************************
 * wzorzec projektowy - PROTOTYP                 *
 * autor: Jaroslaw Wawer        H1ISI            *
 *        j.wawer@stud.elka.pw.edu.pl            *
 *                                               *
 * ZPR - praca domowa                            *
 * Warszawa, 14.04.2008                          *
 *                                               *
 *************************************************/

#include <vector>

/*
 * Klasa bazowa implementujaca interfejs prototypu.
 * Ta klasa posluguje sie uzytkownik, operujac na
 * konkretnych obiektach klas z niej dziedziczacych,
 * ktorch nazw nie musi czesto nawet znac.
 */
class Multimedia{
public:
	/* 
	 * deklaracja czysto wirtualnej funkcji klonuj(),
	 * ktora musi zostac zdefiniowana we wszystkich
	 * klasach dziedziczacych.
	 */
	virtual Multimedia* klonuj() = 0;
	Multimedia(){/* */}
private:
	/*
	 * Prywatny kondtruktor kopiujacy klasy bazowej
	 * pozwala uniknıc najprawdopodobniej blednego
	 * (poniewaz obiekty klasy bazowej nie powinny byc
	 * tworzone) kopiowania obiektow.
	 */
	Multimedia(const Multimedia& );
	/*
	 * Dalsza definicja klasy pominieta dla zachowania
	 * czytelnosci przykladu prototypu
	 */
};

/*
 * Przyklad klasy dziedziczacej z klasy Multimedia, 
 * reprezentujacej konkretne obiekty wykorzystywane 
 * przez uzytkownika. Musi ona implementowac fukncje 
 * klonuj().
 */
class Obraz: public Multimedia {
public:
	Obraz(){/* */}
	/*
	 * Obowiazkowo zdefiniowana funckja klonuj() moze 
	 * wykonac poprawne skopiowanie obektu bez obawy 
	 * o wycinanie.
	 */
	virtual Obraz* klonuj() {
		return new Obraz(*this);
	}
	/*
	 * Konstruktor kopiujacy moze byc juz publiczny 
	 * gdy sa to juz klasy reprezentujace rzeczywiste 
	 * obiekty wykorzystywane przez uzytkownika i sa 
	 * one liscmi w drzewie hierarchi klas wiec nie 
	 * musimy obawiac sie wycinania przy kopiowaniu.
	 */
	Obraz(const Obraz& ){};
};

/*
 * Przyklad klasy dziedziczacej z Multimedia.
 * Patrz: opis klasy Obraz.
 */
class Muzyka: public Multimedia {
public:
	Muzyka(){/* */}
	virtual Muzyka* klonuj() {
		return new Muzyka(*this);
	}
	Muzyka(const Muzyka& ){};
};

/*
 * Przyklad klasy dziedziczacej z Multimedia.
 * Patrz: opis klasy Obraz.
 */
class Film: public Multimedia {
public:
	Film(){/* */}
	virtual Film* klonuj() {
		return new Film(*this);
	}
	Film(const Film& ){};
};


/*******************************************
 * Przyk³ad wykorzystania wzorca prototyp. *
 *******************************************/
int main(){
	std::vector<Multimedia*> katalog;
	katalog.push_back(new Obraz);
	katalog.push_back(new Muzyka);
	katalog.push_back(new Film);
	/*
	 * W wektorze katalog znajduja sie wskazniki
	 * do 3 obiektow klas dziedziczacych z klasy
	 * Multimedia, lecz sa to wskazniki na obiekty
	 * klasy bazowej.
	 */

	std::vector<Multimedia*> plytka_kopia_katalogu = katalog;
	/*
	 * Tak wykonana kopia katalogu zawieralaby 
	 * jedynie wskazniki na te same obiekty, a 
	 * zapewne nie o to nam chodzi, jesli ma byc
	 * to na przyklad kopia dla innego uzytkowniki 
	 * lub kopia zapasowa.
	 */

	std::vector<Multimedia*> kopia_katalogu;
	for(std::vector<Multimedia*>::iterator it = katalog.begin(); it != katalog.end(); ++it){
		kopia_katalogu.push_back( (*it)->klonuj() );
	}
	/*
	 * Dopiero tak wykonana kopia dzieki wykorzystaniu
	 * wirtualnej funkcji klonuj() wykona poprawna kopie 
	 * wszystkich obiektow. Jest to jeden z przykladow
	 * zastosowania wzorca prototypu.
	 */

	return 0;
}