Singleton Pattern passend hierfür?

  • Themenstarter Themenstarter SilentBob
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
S

SilentBob

Gast
Hallo,

Ich habe einen JFrame mit bisher 6 TabbedPanes drin, könnten auch bis zu 10 werden.

Nun haben diese 6 GUI Klassen zur Unterscheidung namen wie xxxView während die dazugehörigen Klassen mit den Methoden xxxControl heißen und evtl. gibts noch xxxModel Klassen die Daten aufnehmen.

Nun sind das ganze ca. 15 Klassen. Jede der Klasse greift mehr/weniger auf andere Klassen zu. Nun habe ich natürlich das WirrWarr, dass ich die erzeugten Objekte der GUI KLassen oder die Objekte der Control Klassen überall hindurchreichen muss, denn ein 2. Objekt der GUI Klasse geht nicht, da ich sonst einen NullPointer bekomme. Das ganze sieht dann natürlich nicht so elegant aus und viele KLasse haben 3 Parameter im Konstruktor.

Nun frage ich mich ob es nicht ideal wäre das Singleton Pattern hier anzuwenden:

1. damit objekte auch sicher nur einmal erzeugt werden und ich nicht immer darauf achten muss ja das Objekt richtig weiterzugeben etc

2. damit ich eine angebliche so las ich es GLOBALE Stelle habe wo ich das Objekt abholen kann. Wäre super geschickt, wenn ich nicht immer von hir nach da und dort das Objekt reiche...

3. und das Single-Objekt wird nur erstellt wenns benötigt wird, spart Ressourcen.

Ist das Singleton ok für diesen Anwendungsfall? was denkt Ihr? Hat mir vielleicht jemand gute Links mit Anwendungsfällen dieser Komplexität?
 
ms hat gesagt.:
Code:
public class MainWindow extends JFrame
{   
   public MainWindow() throws IOException
   {
      super("Test"); 

      XmlDaten xmlDaten = leseXmlDaten();
      
      InvoicePanel invoicePanel = new InvoicePanel();
      invoicePanel.setDaten(xmlDaten);

      SettingsPanel settingsPanel = new SettingsPanel();
      settingsPanel.setDaten(xmlDaten);

      jtp.addTab("Invoice", invoicePanel);   
      jtp.addTab("Settings", settingsPanel);
   
      add(jtp);
     
      ...     
   }

   private XmlDaten leseXmlDaten() {
   
      // ... hier werden die Daten gelesen und zurückgegeben

      return ...
   }

}

edit: InvoicePanel und SettingsPanel müssen natürlich mit den XmlDaten umgehen können.
Noch besser wäre es wenn man eine Referenz auf eine Modelklasse mitgibt, damit die Actions gleich darauf arbeiten können.

ms

müsste das nicht
Code:
invoicePanel.setDaten(leseXmlDaten())
heißen ? Das X ist einmal groß und einmal kleingeschrieben, daher verwirrend.

Naja eine leseXMLDAten Funktion in einer View sprich JFrame orientiert sich aber nicht sehr start an der Trennung von View und Model oder?

Noch besser wäre es wenn man eine Referenz auf eine Modelklasse mitgibt, damit die Actions gleich darauf arbeiten können.

meinst du mit Referenz die Instanz meiner SettingsData Klasse wo alle xml Daten drin sind? yo diese Referenz wäre dann in der leseXmlDaten() methode.
 
Alle X sind richtig.

Eine Methode hält in dem Sinn keine Referenzen so wie es Objekte tun.
Ich verstehe deine Frage nicht ganz.

invoicePanel.setDaten(leseXmlDaten())
Du willst die Daten doch auch im SettingsPanel haben, oder?
Also einmal Lesen und die Referenz den beiden Panels die Referenz übergeben.

ms
 
oh man meine Augen...

Ich dachte:
Code:
XmlDaten xmlDaten = leseXmlDaten();

das heißt
Code:
XmlDaten xmlDaten = new XmlDaten();

jetzt verstehe ich erst den Zusammenhang bzw. warum das eine X groß/klein ist hehe

1.) Ich nehme an, dass deine Methode leseXmlDaten() meiner methode loadXMLData() entspricht, wenn ja dann habe ich zwar eine Referenz in dem objekt xmlDaten und übergebe das objekt dem InvoicePanel/SettingsPanel doch dann bräuchte ich ja noch getxx Methoden in beiden Panel-Klassen die das objekt auslesen und die daten in die JCBoxen schreiben richtig?

2.) Was mich wundert ist, dass du die leseXmlDaten() methode in die View schreibst? OK es gibt 1000 verschiedene anwendugsarten und spezielle Problemfälle ich bin auch der Meinung, dass man MVC etc nicht in jedes Schema pressen kann ;-)
 
So das einlesen in beide JComboboxen geht erstmal, ob es so ist wie dus gerne hättest bin mir net 100% sicher...


Code:
public class MainWindow extends JFrame
{    
   static final long serialVersionUID = 1L;   
   private JTabbedPane jtp = new JTabbedPane();   
   private SettingsData settingsdata = new SettingsData();
   public MainWindow() throws IOException
   {
	  super("Test");  
   
	  SettingsData settingsData = loadXMLData(); 
	  
	  InvoicePanel invoicePanel = new InvoicePanel(); 
	  invoicePanel.setDaten(settingsData); 	  
	  
	  SettingsPanel settingsPanel = new SettingsPanel();
	  settingsPanel.setDaten(settingsData); 
	  
      jtp.addTab("Invoice", invoicePanel);  
      jtp.addTab("Settings", settingsPanel); 
    
      add(jtp); 
      
      setResizable(false);      
      setSize(400,400);
      setLocationRelativeTo(null);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     
      setVisible(true);	
      
   }
   
   public SettingsData loadXMLData()
	{ 		
		try
		{ 
           JAXBContext jc = JAXBContext.newInstance(SettingsData.class);
           Unmarshaller um = jc.createUnmarshaller ();           
	       Object o = um.unmarshal(new FileInputStream("test.xml"));
	       settingsdata = (SettingsData) o; 	       
	         
      }
	   catch (Exception e)
	   {
       e.printStackTrace (); 
      }
	   
	   return settingsdata;
	   
	}
       
   public static void main(String []args) throws Exception
   {  
	      
	      EventQueue.invokeLater(new Runnable()
	      {
		      public void run()
		      {	      
				try 
				{ 				
					new MainWindow(); 
				}
				catch (IOException e)
				{				
					e.printStackTrace();
				}	                    
		      }
	      });  	      
   }
}


Code:
public class InvoicePanel extends JPanel
{	 	
	private static final long serialVersionUID = 1L;
    JComboBox jcb = new JComboBox();

	public InvoicePanel()
    {   
		setLayout(null);
		add(jcb);		
		jcb.setBounds(0,0,200,30);
    }
	
	public void setDaten(SettingsData settingsData)
	{
		for(int i = 0 ; i < settingsData.getListCurrencyFormat().size() ; i++)
        {
        	jcb.addItem(settingsData.getListCurrencyFormat().get(i));	        	
        }		
	}	   
}


Code:
public class SettingsPanel extends JPanel
{	 	
	private static final long serialVersionUID = 1L;
	JComboBox jcb = new JComboBox();

	public SettingsPanel()
    {  		
		setLayout(null);
		add(jcb);		
		jcb.setBounds(0,0,200,30);
    }
	
	public void setDaten(SettingsData settingsData)
	{
		for(int i = 0 ; i < settingsData.getListCurrencyFormat().size() ; i++)
        {
        	jcb.addItem(settingsData.getListCurrencyFormat().get(i));	        	
        }		
	}	    
}


Was ich nicht ganz verstehe ist , warum kann ichs net so machen:

Code:
// fällt weg, da methodenaufruf in methode eh settingsData zurückgibt...
//SettingsData settingsData = loadXMLData(); 
	  
InvoicePanel invoicePanel = new InvoicePanel(); 
invoicePanel.setDaten(loadXMLData()); 	  
	  
SettingsPanel settingsPanel = new SettingsPanel();
settingsPanel.setDaten(loadXMLData());
 
Damit hast du insofern eine lose Kopplung, als dass du dieses Panel auch in einem komplett anderen Programm verwenden könntest, eine eigenständige Komponente sozusagen.
Derjenige, der diese Komponenten zu einem Programm zusammenfügt muss natürlich dafür sorgen, dass die Daten gesetzt werden.

Ok solangsam kapier ichs... obiges heißt also weil ich die setDaten(...) Methode benutze ist die Panel GUI unabhängig, denn man kann muss aber net diese Methode aufrufen, daher kann ich den panel auch in einem anderen Programm nutzen sozusgen, da keine direkte Abhängigkeit zu den xml Daten besteht. Ok würde ich den Panel als eigentständige Komponente nutzen und rufe die setDaten nicht auf sprich sie wird nicht benötigt in dem anderen Programm sollte ich sie ja löschen da Speicherverschwendung auch wenn sie net aufgerufen wird oder?
 
was ich mich jetzt auch noch frage ist:

Ich habe mehrere Klassen die Informationen aus der xml datei benötigen. Diese Informationen sind in dem settingsData Objekt drin und werden in die GUI sprich SettingsPanel geschrieben. Soll ich nun die Infos direkt aus dem Objekt settingsData lesen oder auf die GUI zugreifen und hier auslesen, wie handhabt man das am Besten allgemein?
 
rein prinzipiell neige ich dazu die daten ausschließlich aus der datenquelle zu beziehen, die GUI holt sie sich und zeigt nur an, und is mit ausnahme der nutzereingaben nicht für datenbereitstellung konzipiert, also in meinen programmen
 
SilentBob hat gesagt.:
Ok würde ich den Panel als eigentständige Komponente nutzen und rufe die setDaten nicht auf sprich sie wird nicht benötigt in dem anderen Programm sollte ich sie ja löschen da Speicherverschwendung auch wenn sie net aufgerufen wird oder?
Du willst die Methode setDaten(...) in einem anderen Programm löschen weil du sie dort nicht brauchst?
Wenn du prinzipiell so vor gehst dann müsstest du ja auch alle nicht benötigten Methoden aus der Java-Api löschen. :autsch:
Oder meinst du was anderes?

SilentBob hat gesagt.:
Ich habe mehrere Klassen die Informationen aus der xml datei benötigen. Diese Informationen sind in dem settingsData Objekt drin und werden in die GUI sprich SettingsPanel geschrieben. Soll ich nun die Infos direkt aus dem Objekt settingsData lesen oder auf die GUI zugreifen und hier auslesen, wie handhabt man das am Besten allgemein?
Mit dem MVC-Pattern.

ms
 
Ich nehme mal Bezug auf das Ursprungsposting, ohne die restlichen Antworten alle durchzuarbeiten:

grundsätzlich denke ich, dass eine Trennung von View und Mode und Controller eine sehr sinnvolle Sache ist (MVC hat was). Das Problem ist, dass man das schön durchhält, wenn man ein oder zwei GUI's hat. Bei 6 bis 10 wächst das ganz ordentlich an. Das werden sehr viele Klassen. Aber was macht das? Das ist vielleicht für den Entwickler oder für einen selbst, wenn man 6 Monate später reinschaut zunächst ein bisschen viel, aber im Endeffekt bleiben es 3 grob 3 Klassen je GUI.

Stellt sich die Frage der Übersichtlichkeit.

Bleibt der Quellcode übersichtlicher wenn man ein "Singleton" verwendet? Ich denke wenn man sich mit dem Grundgedanken, was das Singleton-Pattern soll, auseinandersetzt, wird man herausfinden, dass Singleton nicht die Lösung ist.
Ein Singleton System soll sicherstellen, dass in einer Java-Virtual-Machine nur eine Instanz des Objekts existiert. Als Anwender möchte ich aber bei einer GUI ruhig mal ein zweites oder drittes Fenster öffnen. das Singleton würde mir das verbieten.

Deshalb würde ich empfehlen, dass man eine "Main" Klasse entwickelt, die alle Sub-GUIS (JPanels?) instanziiert. Im Konstruktur wird bei meinen Lösungen im Regelfall die Mainklasse mitgegeben. Kommunkation erfolgt über das Listener-Konzept. Dadurch werden aber noch ein paar zusätzliche Klassen notwendig, aber man sollte bedenken, dass Progrmmierung nicht nur aus Quellcode besteht. Javadoc - und das ist echt eine tolle Sache - gehört meines Erachtens auch dazu.
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben