Verständnisfrage Programmentwurf



  • Hallo zusammen,
    ich möchte mir ein variables Menü für die Konsole programmieren.
    Folgende Ausgangssituation:
    Ich habe ein Hauptmenü mit 5 Menüpunkten (Ebene 1). Jedes dieser 5 Menüpunkte soll maximal 5 weitere Untermenüpunkte bereitstellen.
    Also sind wir jetzt bei 5*5 Menüpunkten maximal. (Ebene 2)
    Es soll aber noch eine 3. Eben dazu kommen, bei der nochmal jedes dieser 5 Untermenüpunkte maximal 5 Unterpunkte enthalten soll.
    Somit wären wir bei 5*5*5 maximal mögliche Menüpunkte.

    Meine Frage ist jetzt wie ich das in C++ umsetzen kann. Erstelle ich eine Klasse für das Hauptmenü und leite davon dann jeweils eine Klasse pro Ebene ab und hätte somit maximal 3 Objekte zu erstellen, oder sollte ich für jeden Menüpunkt ein Objekt erstellen?
    Das Ziel soll hier sein, dass ich bei der Erstellung des Menüs angeben kann, wieviele Unterpunkte benötigt werden.
    Ein Beispiel:

    1, 2, 3, 4, 5 (Menüpunkte im Hauptmenü)
    jetzt soll unter Menüpunkt 1 weitere 3 Unterpunkte vorhanden sein:
    1.1, 1.2, 1.3 aber 1.4 und 1.5 sollen nicht belegt sein
    Und unter Menüpunkt 2 sollen 5 Unterpunkte erstellt werden:
    2.1, 2.2, 2.3, 2.4, 2.5
    Unter Hauptmenüpunkt 3, 4 und 5 sollen z.B. jeweils direkt zu der Aufgabe führen.

    So dass ich mir im Endeffekt später für verschieden Aufgaben ein entsprechendes Menü zusammenstellen kann. Wichtig soll hier auch sein, dass, wenn ich die Menüpunkte 1.1, 1.2, 1.3 habe, der Menüpunkt 1.4 und 1.5 nicht auswählbar sind.

    Ich wäre für ein paar Denkanstöße sehr dankbar.

    Vielen Dank im Voraus,
    mkG Nas



  • Schau dir einfach mal GUI-Frameworks an. Läuft eigentlich so gut wie immer auf Menu und MenuItem heraus.



  • Sowas ist ein einfaches Beispiel für das Composite Entwurfsmuster.
    Ein Menu besteht aus Einträgen, die jeweils irgendeinen Befehl darstellen oder wieder ein Menu sind.
    Mal ein Beispiel:
    Znächst eine Schnittstelle für alle Einträge in einem Menu

    // menu_item.hpp
    #include <string>
    class MenuItem
    {
    public:
    	virtual const std::string& Name() const = 0;
    	void operator()() const
    	{
    		std::cout << "Ihre Wahl: " << Name() << "\n";
    		Perform();
    	}
    private:
    	virtual void Perform() const = 0;		
    };
    

    Ein Eintrag der nicht ein Untermenu ist, ist z.B. so implementiert:

    // menu_command.hpp
    #include "menu_item.hpp"
    #include <memory>
    #include <functionl>
    
    typedef std::function<void (void)> Action;
    
    class MenuCommand : public MenuItem
    {
    public:
    	static std::shared_ptr<MenuItem> Create(const std::string& name, Action action)
    	{
    		return std::shared_ptr<MenuItem>(new MenuCommand(name, action));
    	}
    
    	const std::string& Name() const
    	{
    		return name_;
    	}
    
    private:
    	MenuCommand(const std::string& name, Action action) :
    		action_(action), name_(name)
    	{
    	}
    
    	void Perform() const
    	{
    		action_();
    	}
    
    	std::string name_;
    	Action action_;
    };
    

    Ein Menu, egal ob Hauptmenu unter Untermenu ist auch ein MenuItem:

    // menu.hpp
    #include "menu_item.hpp"
    #include <ostream>
    #include <vector>
    
    class Menu : public MenuItem
    {
    public:
    	static std::shared_ptr<Menu> Create(const std::string& name, std::ostream& os = std::cout)
    	{
    		return std::shared_ptr<Menu>(new Menu(name, os));
    	}
    
    	Menu(const std::string name, std::ostream& os = std::cout) :
    	  name_(name), os_(&os)
    	{
    
    	}
    
    	Menu& AddItem(std::shared_ptr<MenuItem> item)
    	{
    		items_.push_back(item);
    		return *this;
    	}
    
    	Menu& AddSubMenu(const std::string& name)
    	{
    		std::shared_ptr<Menu> sub = Menu::Create(name, *os_);
    		AddItem(sub);
    		return *sub;
    	}
    
    	const std::string& Name() const
    	{
    		return name_;
    	}
    
    	void Print() const
    	{
    		(*this)();
    	}
    
    private:
    	void Perform() const
    	{
    		for(;;) 
    			if (!PrintMenu()) break;
    	}
    
    	bool PrintMenu() const
    	{
    		*os_ << "\nMenu: " << Name() << "\n";
    		for(size_t n = 0; n < items_.size(); ++n)
    			*os_ << n << ": " << items_[n]->Name() << "\n" ;
    		*os_ << items_.size() << ": Zurueck\n";
    		size_t index = items_.size() + 1;
    		if (!(std::cin >> index) || index >= items_.size())
    			return false;
    		const MenuItem& m = *items_[index]; 
    		m();
    		return true;
    	}
    
    private:
    	std::string name_;
    	std::ostream* os_;
    	std::vector<std::shared_ptr<MenuItem> > items_;
    };
    

    Anwendung:

    void MachNix()
    {
    	std::cout << "Ich mach joarnix\n";
    }
    
    class MachWas
    {
    public:
    	void operator()() const
    	{
    		std::cout << "ich mach was\n";
    	}
    };
    
    int main(int argc, char* argv[])
    {
    	using namespace std;
    
    	Menu mainMenu("Hauptmenu");
    
            // Bsp mit lambda
    	mainMenu.AddItem(MenuCommand::Create("Hallo Welt", [](){std::cout << "\nHallo Welt!\n";}));
    
            // Bsp mit Zeiger auf Funktiom
    	mainMenu.AddSubMenu("Untermenu 1").AddItem(
    		MenuCommand::Create("Mach nix", MachNix));
    
            // Bsp mit Funktionsobjekt 
    	mainMenu.AddSubMenu("Untermenu 2").
    		AddItem(MenuCommand::Create("Mach mal was", MachWas())).
    		AddSubMenu("Untermenu 2.1").
    			AddItem(MenuCommand::Create("Mach mal was", MachWas()));
    
    	mainMenu.Print();
    
    	return 0;
    }
    

    Diese verketteten Aufrufe sind Geschmackssache, man kann es natürlich auch anders machen.



  • Damit kann ich schonmal etwas anfangen,
    besten Dank.

    mkG Nas



  • Hat zufällig jemand eine gute Einführung zum Thema "Composite Pattern". Vielleicht auch irgendwas zum Thema Design Pattern von Unis, wäre für jede Hilfe dankbar!

    mkG Nas



  • Reicht dir diese BEschreibung als Ansatzpunkt?



  • Das hatte ich schon vorher gefunden. Ich weiß, auch wenn es Standard sein sollte, dass viele erst Fragen und, wenn überhaupt, dann erst selber suchen. Ich gehöre nicht zu der Gruppe. Da ich noch Anfänger bin, habe ich noch keine Quelle gefunden, die es leicht verdaulich beschreibt. Aber ich gebe auch gerne zu, dass das Thema zur Zeit ein wenig ausserhalb meines Horizontes liegt 😉

    mkG Nas



  • Hast du auch mal die dort angegebenen weiterführenden Links und Literaturhinweise ausprobiert? Das hier ist eigentlich das Standardwerk zum Thema Design Patterns:
    Entwurfsmuster | ISBN: 3827321999


Anmelden zum Antworten