OOP Gui, Logik und Datenbank richtig aufbauen

Meeresgott

Bekanntes Mitglied
Hallo liebes Forum,

Die letzten Tage habe ich damit verbracht zu lernen, wie man eine GUI die auf eine Datenbank zugreift am besten programmiert.

Im wesentlichen gibt es drei Ebenen:
  1. Die Gui selber
  2. Eine Logik, die die Daten der Gui auswertet
  3. Die Datenbank
Da diese Elements sauber voneinander getrennten werden sollten entschied ich mich für ein Interface.
Ich habe dazu ein kleines Beispiel programmiert.

Die GUI besteht aus einem JTextField, JButton und einem JLabel. Je nach dem, was in dem TextField eingeben wird ändert sich der Text des JLabels. (Ich weiß etwas unkreativ ;) )


Hier der Code der GUI:
Java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

/**
*
* GUI.java
*/
public class GUI
{
    private JFrame frame;
    private JButton button;
    private JTextField textField;
    private JLabel label;
  
    private boolean guiEvent = false;
  
    private GuiData guiData = null;
  
    public void buildGUI()
    {
        frame = new JFrame();
        frame.setTitle("GUI - Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
        label = new JLabel("This is a Text");
        frame.add(BorderLayout.NORTH,label);
      
        textField = new JTextField(20);
        frame.add(BorderLayout.CENTER,textField);
      
        button = new JButton("Rename");
        button.addActionListener(new RenameActionListener());
        frame.add(BorderLayout.SOUTH,button);
      
        frame.pack();
    }
  
    public void showGUI()
    {
        frame.setVisible(true);
    }
  
    public void waitOfUserEvent()
    {
        while(!guiEvent){
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException ex) {
                Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
  
    public GuiData getUserEvent()
    {
        return guiData;
    }
  
    public void setUserEvent(GuiData data)
    {
        if(data instanceof ButtonEventAnswer)
        {
            ButtonEventAnswer bea = (ButtonEventAnswer) data;
            label.setText(bea.getTitle());
            textField.setText("");
        }
        guiEvent = false;
    }
  
    public class RenameActionListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            ButtonEvent event = new ButtonEvent();
            event.setText(textField.getText());
          
            guiData = event;
            guiEvent = true;
        }
      
    }
}


Die "Familie" GuiData die ich als Schnittstelle nutze.
Java:
interface GuiData {}

Java:
public class ButtonEvent implements GuiData
{
    String text;
  
    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
Java:
public class ButtonEventAnswer implements GuiData
{
    String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
Meine Logik zum auswerten
Java:
public class GuiExample {

    public static void main(String[] args)
    {
        Database base = new Database();
        base.init();
      
        GUI gui = new GUI();
        gui.buildGUI();
        gui.showGUI();
        System.out.println("Fin");
        while(true)
        {
            gui.waitOfUserEvent();
            GuiData data = gui.getUserEvent();
          
            if(data instanceof ButtonEvent)
            {
                ButtonEvent event = (ButtonEvent) data;
                String answer = base.getRequestAnswer(event.getText());
                System.out.println(answer);
                ButtonEventAnswer bea = new ButtonEventAnswer();
                bea.setTitle(answer);
              
                gui.setUserEvent(bea);
            }
        }
    }
  
}

Zuguterletzt die "Datenbank"
Java:
public class Database
{
    private Map<String,String> base;
  
    public void init()
    {
        base = new TreeMap();
      
        base.put("Test", "TestValue");
        base.put("Auto", "Audi");
        base.put("Programm", "Excel");
    }
  
    public String getRequestAnswer(String s)
    {
        return base.get(s);
    }
}

Jetzt zu meinen Fragen:
  • Ist es Sinnvoll es so zu machen?
  • wie macht man es regulär?
  • wie würdet ihr es umsetzten?
  • gibt es vielleicht in hinblick auf OO bessere Prinzipien?

Ich danke schon mal für eure Antworten :)

Viele Grüße,

Meeresgott

Edit:
Vielleicht ist es noch wichtig zu wissen, dass ich nach einem Muster/Konzept oder ähnliches suche, was ich bei einer recht komplexen GUI anwenden kann, dass nicht stark anfällig für Veränderungen ist.
 
Zuletzt bearbeitet:

stg

Top Contributor
Deine Schnittstelle ist merkwürdig und erfüllt irgendwie keinen Zweck. Allein die Tatsache, dass du da casten musst und mit isntanceof prüfen musst, ist schon ein Indiz dafür, dass da was krumm ist.. Solange du einfache Strings o.Ä. hin und her schiebst, belasse es einfach bei den Strings. Willst du mehrere Informationen auf einmal austauschen, dann erstelle einfache POJOs als Datentransferobjekt. Zusätzlicher Interfaces bedarf es da nicht. Die würde ich erst einführen, wenn du Logik in diesen Objekten kapseln willst, was nach außen evetuell zu viel preisgeben könnte oder dafür sorgen würde, dass die GUI ohne zusätzliche Libs nicht mehr kompilierbar ist.
Gut an deiner GUI Klasse finde ich, dass du klar den Aufbau der GUI selbst vom Rest trennst und auch nicht einfach blind von JFrame erbst, sondern stattdessen Kompositionen nutzt.
Deine ActionListener sind etwas unglücklich und fehleranfällig. Wenn du einen der ActionListener an anderer Stelle nutzen willst, wirst du darüber stolpern, dass der ActionListener weiß, zu welchem Button er gehört. Die Information, auf welchem Button er ausgelöst wurde, erhältst du auch aus dem Event-Objekt. Willst du ihn wirklich nur an dieser einen Stelle nutzen, dann verwende besser eine anonyme innere Klasse.
Zu deiner "Datenbank" kann man natürlich nicht viel sagen. Zum herumprobieren ist das OK so.
Zwischen Datenbank und Anwendungslogik würde ich eine weitere Schicht einführen, welche die Datenbank komplett von der Anwendung entkoppelt. Die Geschäftslogik sollte gar nicht wissen, dass es eine Datenbank gibt. Hier kannst du benötigte elementare Grundoperationen bereitstellen "findeAlleAutos(), speichereEmailAdresseDesBenutzers()....". Der Anwendung ist es dann egal, wie und von wo die Daten beschaffen werden, und zudem wird der Anwendungscode schlanker.
 

Meeresgott

Bekanntes Mitglied
Diese Merkwürdige Schnittstelle ist auch mein Dorn im Auge. Allerdings weiß ich mir da nicht ganz zu helfen.
Die Vorteile die man hat bei dieser "Art" sind, dass je nach dem welches Object vom Typ GuiData überliefert bekommt die Logik genau weiß welches Event eingetroffen ist und alle Daten zum entsprechenden Event bereits bekommt. Allerdings echt nicht schön und ich bin mir ziemlich sicher das instanceof eigentlich anders genutzt werden sollte.
Hier in dem Beispiel schiebe ich nur Strings hin und her allerdings in der Application für die ich das ganze ausarbeite teils ganze Lists von Objekten.
Ich würde eine Status Abfrage bei einem POJO so realiseren:

Code:
public class DatenPOJO
{
    private EventArt eventArt;
 
    private String jTextFieldString;

    public EventArt getEventArt() {
        return eventArt;
    }

    public void setEventArt(EventArt eventArt) {
        this.eventArt = eventArt;
    }

    public String getjTextFieldString() {
        return jTextFieldString;
    }

    public void setjTextFieldString(String jTextFieldString) {
        this.jTextFieldString = jTextFieldString;
    }
 
    public enum EventArt
    {
        BUTTON_RENAME,
        BUTTON_ERASE
    }
}

Die GUI-Klasse habe ich nun um einen JButton erweitert. So dass es mehrer Events geben kann.
Dieser Button heißt Erase und löscht einfach den Inhalt des Labels.
Den ActionListener habe ich ebenfalls Überarbeitet.
Java:
public class GUI
{
    private JFrame frame;
    private JButton buttonRename;
    private JButton buttonErase;
    private JTextField textField;
    private JLabel label;
 
    private boolean guiEvent = false;
 
    private DatenPOJO guiData = null;
 
    public void buildGUI()
    {
        frame = new JFrame();
        frame.setTitle("GUI - Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
        label = new JLabel("This is a Text");
        frame.add(BorderLayout.NORTH,label);
     
        textField = new JTextField(20);
        frame.add(BorderLayout.CENTER,textField);
     
        JPanel buttons = new JPanel();
        buttons.setLayout(new GridLayout(1,2));
        ButtonActionListener bal = new ButtonActionListener();
     
        buttonRename = new JButton("Rename");
        buttonRename.addActionListener(bal);
        buttons.add(buttonRename);
     
        buttonErase = new JButton("Erase");
        buttonErase.addActionListener(bal);
        buttons.add(buttonErase);
     
        frame.add(BorderLayout.SOUTH,buttons);
     
        frame.pack();
    }
 
    public void showGUI()
    {
        frame.setVisible(true);
    }
 
    public void waitOfUserEvent()
    {
        while(!guiEvent){
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException ex) {
                Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
 
    public DatenPOJO getUserEvent()
    {
        return guiData;
    }
 
    public void setUserEvent(DatenPOJO data)
    {
        switch(data.getEventArt())
        {
            case BUTTON_RENAME:
                label.setText(data.getjTextFieldString());
                break;
             
            case BUTTON_ERASE:
                label.setText("");
                break;
        }
        guiEvent = false;
    }
 
    public class ButtonActionListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            JButton button = (JButton) e.getSource();
            DatenPOJO pojo = new DatenPOJO();
         
            if(button.equals(buttonRename))
            {
                pojo.setEventArt(DatenPOJO.EventArt.BUTTON_RENAME);
                pojo.setjTextFieldString(textField.getText());
            }
            else if(button.equals(buttonErase))
            {
                pojo.setEventArt(DatenPOJO.EventArt.BUTTON_ERASE);
            }
         
            guiData = pojo;
            guiEvent = true;
        }
     
    }
}
Die Logik habe ich nun aus der main()-Methode raus genommen und ihr ein eigenes Objekt gegönnt.
Es sind zwei neue Methoden dazugekommen zur Auswertung des UsersEvents

Java:
public class GuiExample {

    private Database base;
    private GUI gui;
 
    public GuiExample()
    {
        base = new Database();
        base.init();
     
        gui = new GUI();
        gui.buildGUI();
    }
 
 
    public void startApplication()
    {
        gui.showGUI();
        while(true)
        {
            gui.waitOfUserEvent();
            DatenPOJO data = gui.getUserEvent();
         
            switch(data.getEventArt())
            {
                case BUTTON_RENAME:
                    rename(data);
                    break;
                         
                case BUTTON_ERASE:
                    erase(data);
                    break;
            }
        }
    }
 
    public void rename(DatenPOJO pojo)
    {
        String name = base.getRequestAnswer(pojo.getjTextFieldString());
        pojo.setjTextFieldString(name);
     
        gui.setUserEvent(pojo);
    }
 
    public void erase(DatenPOJO pojo)
    {
        //Tu irgendwas hier mit dem POJO
     
        gui.setUserEvent(pojo);
    }
 
    public static void main(String[] args)
    {
        GuiExample example = new GuiExample();
        example.startApplication();
    }
}

Die "Datenbank" ist extra so simple gehalten da mir kein einfacheres Beispiel einfällt. Die eigentlich Datenbank ist eine MySql-Database aber das ist (so hoffe ich) in diesem Beispiel egal.
Das mit der weiteren Schicht zwischen Datenbank und Logik verstehe ich nicht ganz. Deshalb habe ich Sie oben nicht umgesetzt. Könntest du mir da noch ein Stups in die richtige Richtung geben?

Viele Grüße,
Meeresgott

P.S.
Ich habe die "Datenbank" für ein bessere Verständnis nun so umgeschrieben, dass die eMail eines Users ausgegeben wird bei einer Suche.

Java:
        base.put("Andre", "andre@gmail.com");
        base.put("Timo", "timo@gmail.com");
        base.put("Alexander", "alexander@gmail.com");
 

XyMorgan

Aktives Mitglied
public void startApplication()
{
gui.showGUI();
while(true)
{
gui.waitOfUserEvent();
DatenPOJO data = gui.getUserEvent();

switch(data.getEventArt())
{
case BUTTON_RENAME:
rename(data);
break;

case BUTTON_ERASE:
erase(data);
break;
}
}
}

und

public static void main(String[] args)
{
GuiExample example =new GuiExample();
example.startApplication();
}

bricht die Regeln der Swing-Programmierung, du blockierst den EventDispatcher. Besser:

Java:
public static void main(String[] args)
  {
        GuiExample example =new GuiExample();
        SwingUtilities.invokeLater (
                    new Runnable() {
                        public void run() {
                  example.startApplication();
                        }
                    }
                );
  }

Dein Event-Handling ist für mich nicht nachvollziehbar, Event-Handling solltest du Swing anvertrauen.
Entweder MVC oder simple Listener einbinden.

Grobkonzept, vor allem wenn es mal gegen eine Remote-Datenbank geht:

Context
GUI
Datenbank (Transactions) Manager
DAO(s)
(Datenbank)

Context (weil Beispiel, real kommen die Daten ja sonst woher, über JDBC, Webservice oder...)
In der GUI Daten anzeigen/erfassen. Bei Klick auf die entsprechenden Buttons über Listener den Manager anweisen über die DAOs die Daten zu lesen oder zu schreiben.

Hänge mal ein grobes zusammengezimmertes Beispiel an

Java:
package de.db;

public final class ApplicationContext {
   
    private final static DataBase db = new DataBase();
    private final static  DataBaseManager dbManager = new DataBaseManager(db);
   
    public static DataBase getDataBase() {
        return db;
    }
   
    public static DataBaseManager getDatabaseManager() {
        return dbManager;
    }

}
Java:
package de.db;

public interface Dao {
    public DataBase getDataBase();
}
Java:
package de.db;

public class DataAcessException extends Exception {

    public DataAcessException(String message) {
        super(message);
    }

    public DataAcessException(String message, Throwable cause) {
        super(message, cause);
        // TODO Auto-generated constructor stub
    }
}
Java:
package de.db;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class DataBase {

    private Map<String, String> base;

    public void init() {
        base = new TreeMap<String, String>();

        base.put("Test", "TestValue");
        base.put("Auto", "Audi");
        base.put("Programm", "Excel");
    }

    public String getRequestAnswer(String s) {
        return base.get(s);
    }

    public UserData getUserMail(String userName) throws DataAcessException {
        if (base.containsKey(userName)) {
            String email = base.get(userName);
            UserData userData = new UserData();
            userData.setUserName(userName);
            userData.setEmail(email);
            return userData;
        } else {
            throw new DataAcessException("Invalid Username");
        }
    }

    public List<UserData> getAllUser() {
        return Collections.emptyList();
    }

}
Java:
package de.db;

import java.util.List;

public class DataBaseManager {
    private DataBase dataBase;
    private GetDataDao getDataDao;
    private PutDataDao putDataDao;
   
    public DataBaseManager(DataBase dataBase) {
        this.dataBase = dataBase;
        getDataDao = new GetDataDao(this);
        putDataDao = new PutDataDao(this);
    }
   
    public UserData getUserMail(String userName) throws DataAcessException {
        return getDataDao.getUserMail(userName);
    }

    public List<UserData> getAllUser() throws DataAcessException {
        return getDataDao.getAllUser();
    }
   
    public void putUserMail(String userName, String userMail) throws DataAcessException {
        putDataDao.putUserMail(userName, userMail);
    }
   
    protected DataBase getDB() {
        return dataBase;
    }
}
Java:
package de.db;

public class DataDao implements Dao{
    private DataBaseManager dataBaseManager;

    public DataDao(DataBaseManager dataBaseManager) {
        this.dataBaseManager = dataBaseManager;
    }
   
    public final DataBase getDataBase() {
        return dataBaseManager.getDB();
    }
}
Java:
package de.db;

import java.util.List;

public class GetDataDao extends DataDao {
   
    public GetDataDao(DataBaseManager dataBaseManager) {
        super(dataBaseManager);
    }

    public UserData getUserMail(String userName) throws DataAcessException {
        return getDataBase().getUserMail(userName);
    }

    public List<UserData> getAllUser() throws DataAcessException{
        return getDataBase().getAllUser();
    }
   
   
    // more to implement
   
}
Java:
package de.db;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JTextField;

public class GUI {

    public void buildGUI() {
        // buid components

        // use textfields && labels or table
        JTextField userNameField = new JTextField();
        JTextField emailField = new JTextField();

        JButton getUserDataButton = new JButton();
        getUserDataButton.addActionListener(new ActionListener() {
            // implement ActionListener on GUI or create class || override
            @Override
            public void actionPerformed(ActionEvent e) {
                // get username from name field and get data from db
                // validation ?
                if (!userNameField.getText().isEmpty()) {
                    try {
                        UserData userData = ApplicationContext.getDatabaseManager().getUserMail(userNameField.getText());
                        emailField.setText(userData.getEmail());
                    } catch (DataAcessException e1) {
                        // log || whatever
                    }
                }
            }
        });

        JButton putUserMailButton = new JButton();
        getUserDataButton.addActionListener(new ActionListener() {
            // implement ActionListener on GUI or create class || override
            @Override
            public void actionPerformed(ActionEvent e) {
                // get username from name field and get data from db
                // validation ?
                if (!userNameField.getText().isEmpty() && !emailField.getText().isEmpty()) {
                    try {
                        ApplicationContext.getDatabaseManager().putUserMail(userNameField.getText(), emailField.getText());
                    } catch (DataAcessException e1) {
                        // log || whatever
                    }
                }
            }
        });

        // add components && prepare frame
       
    }

    public void showGUI() {
        // jframe.setVisible(true); || whatever
    }

}
Java:
package de.db;

import javax.swing.SwingUtilities;

public class GuiExample {

    private GUI gui; // your gui
   
    public GuiExample() {
       
        gui = new GUI();
        // .. your code
    }

    private void startApplication() {
        gui.showGUI();
        // .. your code
    }

    public static void main(String[] args) {
        GuiExample example = new GuiExample();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                example.startApplication();
            }
        });

    }

}
Java:
package de.db;

public class PutDataDao extends DataDao{

    public PutDataDao(DataBaseManager dataBaseManager) {
        super(dataBaseManager);
    }
   
    public void putUserMail(String userName, String userMail) throws DataAcessException {
        // implement.....
    }

    public void createUser(String ... userName) throws DataAcessException {
        // implement.....
    }
   
    // what ever needed here
}
Java:
package de.db;

public class UserData {
    String userName;
    String email;
   
   
   
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
   
   
}


Real wird man ggf. später die Abfragen asynchron machen, damit die Anwendung nicht hängt. Später tauschst dann die DAOs aus, wenn es gegen mysql oder was auch immer geht bzw. nimmst ne entsprechende TransactionManager-Implementierung.

So würde ich das in etwa umsetzen.
 

Meeresgott

Bekanntes Mitglied
Vielen Dank für diese sehr ausführliche Antwort !
Habe jetzt ein wenig damit rum gespielt und finde die Lösung super.

Allerdings habe ich noch ein paar Fragen denn:

private final static DataBase db = new DataBase();
private final static DataBaseManager dbManager = new DataBaseManager(db);

macht ein wenig Probleme da bei der Database die Methode init() aufgerufen werden muss. Ich habe dass jetzt so gelöst indem ich den ApplicationContext veränder habe.

Java:
 private static DataBase db = null;
    private static  DataBaseManager dbManager = null;
  
    public static DataBase getDataBase()
    {
        if(db == null)
        {
            db = new DataBase();
            db.init();
        }
        return db;
    }
  
    public static DataBaseManager getDatabaseManager() {
        if(dbManager == null)
        {
            dbManager = new DataBaseManager(ApplicationContext.getDataBase());
        }
        return dbManager;
    }

wäre es Sinnvoller im Konstruktor von DataBase die Methode init() schon aufzurufen oder ist das soweit in Ordnung?

Dann wäre noch eine andere Frage getDatabase() und getDataBaseManager() sind statisch.
Was wäre schöner ?

Eine Instanz von ApplicationContext zu erzeugen und eine Referenz der GUI im Konstruktor zu übergeben oder die Methoden von ApplicationContext so lassen wie sie jetzt sind ?

Viele Grüße
 

XyMorgan

Aktives Mitglied
Das passt so, init würde ich direkt aufrufen.

Context würde ich so lassen, ist ja wie du geschrieben hast erstmal nur testen für den Connect später auf ne mysql-db. Da gäbe es ja eh keine Instanz von der DataBase, sondern im DataBaseManager nen connect auf die DB. Per JDBC oder besser, da kommt der Context ins Spiel per spring (3rd Party.jar) mit ggf. Transactionmanager und ggf. JDBC-Template. Dann würde dir Spring den Context geben und deine Anwendung als Springanwendung nen SpringContext bekommen und da wäre dann der Manager drin.
Lässt sich recht elegant austauschen.

Wenn du das erstmal nicht (oder nie) ins Auge fasst ist ein statischer Kontext immer ganz Praktisch (auch wenn es ab und an unter Fachleuten diskusionen über Memoryprobleme, Unittesting etc gibt), ist imho durchaus gängige Praxis. Alternative bei Frameworks sonst ggf. per Annotation, spielt aber aus meiner Sicht hier erstmal keine Rolle.

Ggf. kommen späte noch einige Klippen die es zu umschiffen geht, z.B. Thread-Safety, Multithreading, Locking etc. Über kurz oder lang sollte man anfangen sich dann mit aktuellen Frameworks zu beschäftigen und nach und nach den Code anzupassen.
 

Meeresgott

Bekanntes Mitglied
Gut dann ändere ich das erstmal wieder zurück.

Das stimmt mit dem statischen Kontext bin ich ein paar anderen Problemen die vorher hatte aus dem weggegangen.

Deshalb brauche ich auch sauberen Code und nicht solchen den ich da oben geschrieben habe..

Eine Frage hätte ich allerdings noch nehmen wir jetzt mal an die SQL-Datenbank ist auf einem Server und ich versuche Sie mit einem Client zu erreichen.

Habe da jetzt auch von unterschiedlichen Methoden gehört auf die DB zugreifen. Die jetzige DB hat einen Technical-User und einen SocketServer davorgesetzt zur Authentifizierung. Auch an dieser Stelle habe ich (bei den ObjectStreamen) eine instanceof Abfrage und je nach dem welches Objekt kommt bekommt der Client ein anderes zurück. Eigentlich sehr ähnlich zu dem Konzept das ich als erstes in diesen Thread reingepostet habe. Ist das an dieser Stelle vertretbar? Wie sähe eine anständige/saubere Client - Server Kommunikation aus ?

Die andere Methode die Stark vertreten zu sein scheint ist, dass alles über die DB geregelt wird. Allerdings sehe ich dann keine Möglichkeit mehr Passwörter bei vergessen ohne Supporter o.ä. zurück zusetzten ohne dann doch einen Server zu haben der einen Technical-User benutzt.

Viele Grüße
 

XyMorgan

Aktives Mitglied
Ansazt Client->Server->DB passt, ist sagen wir mal Standard. Technical User zur DB vom Server passt auch. UserAccounts für die Anwendung in die DB. Anmeldung an der Anwendung dann im Client mit den UserDaten zum Server, im Server mit Connect vom technical User zur DB Verifizieren. Ok zurück an den Client.

Server erstellt SessionCockie für den angemeldeten User, damit der sich nicht immer bei jeder Anfrage verifizieren muss. Server bietet Services für den Client und übernimmt die Kommunication mit der DB.
Demnach kommt das ganze Codegeraffel mit den DAOs etc. ja dann bei dir in den Server. Und dann client mach nen Connect zum Server.

Und ja, fürs zurücksetzten brauchst den Server und der den techn. User. Für die Datenbank für jeden Benutzer einen "Realen Datenbankbenutzer" anzulegen macht kein Mensch, da müsste ja jeder User mehr oder minder auf die wichtigen Tabellen Prvilegien und Rechte haben und könnte wild rumturnen in der DB.

Passwort zurücksetzten löst man z.B. durch Double-Opt-in wenn es automatisert sein soll, sonst hilft -> nur der ADMIN :)

Das Du über nen Server Kommunizieren willst muss ich oben irgendwie überlesen haben. Dachte eher du hast nur Client<->DB um ne Benutzerdatenbank zu verwalten.
 

mrBrown

Super-Moderator
Mitarbeiter
Guck dir mal Google Guice oder ein ähnliches DI-Framework an, das nimmt dir grad bei solchen Projekten viel Arbeit ab ;)

BTW, den Code hier finde ich als Beispiel nicht wirklich geeignet^^
 

Meeresgott

Bekanntes Mitglied
Ich habe jetzt (so hoffe ich) verstanden wie Dependency Injection funktioniert. Allerdings weiß ich jetzt nicht genau wo ich Ansetzten soll dieses Umzusetzen.

Ich gebe einem Objekt(A) ein anderes Objekt(B) damit A eine Methode auf B aufrufen kann.
Übergebe ich der GUI ein LogikObjekt das ein LogikGuiInterface implementiert und die GUI dann so an die Logik kommt ?

Oder Übergebe ich der Geschäftslogik ein GUI Objekt ?
Oder der Datenbank ein ManagerObjekt ?

Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht..
 

mrBrown

Super-Moderator
Mitarbeiter
Der gesamte DB-Kram kennt sich untereinander, was dabei nach ziemlichem Unsinn aussieht, und die Austauschbarkeit gegen "echte" Implementierungen auch gegen 0 gehen lässt...
Die Daos, über die ja die Daten völlig ohne Kenntnis der wirklichen Herkunft bereitstellen sollen, geben die Datenbank selber preis, und kennen auch noch den DatenBankManager, bieten aber als Interface gar nichts, um die Daten abzufragen...


Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht..
Das lässt sich hier ziemlich gut nutzen, um die Datenbank etc anzubinden, da du damit die Teile automatisch recht entkoppelt hast, und dann auch wild zwischen Implementierungen wechseln kannst
 

Meeresgott

Bekanntes Mitglied
So wie ich das jetzt verstanden habe sähe eine Umsetzung in etwa so aus:

Java:
public interface AbstrakteDatabase
{
    public Map<String,String> getUserList();
    public void init();
}

Java:
public interface AbstrakterDatabaseManager
{
    public UserData getUserMail(String userName)  throws DataAcessException;
   
}

Java:
public class KonkreteDataBase implements AbstrakteDatabase
{
    private Map<String, String> base;

    @Override
    public void init() {
        base = new TreeMap<>();

        base.put("Test", "TestValue");
        base.put("Auto", "Audi");
        base.put("Programm", "Excel");
    }
   
    @Override
    public Map<String,String> getUserList()
    {
        return base;
    }
}

Java:
public class KonkreterDatabaseManager implements AbstrakterDatabaseManager
{
    AbstrakteDatabase adb;
   
    public KonkreterDatabaseManager(AbstrakteDatabase adb)
    {
        this.adb = adb;
        this.adb.init();
    }

    @Override
    public UserData getUserMail(String userName)  throws DataAcessException
    {
        if (adb.getUserList().containsKey(userName))
        {
            String email = adb.getUserList().get(userName);
            UserData userData = new UserData();
            userData.setUserName(userName);
            userData.setEmail(email);
            return userData;
        } else {
            throw new DataAcessException("Invalid Username");
        }
    }
}

und in dieser Klasse sage ich dann ganz bestimmt welche Implementierung ich haben möchte
Java:
public class ApplicationContext {
   
    private static AbstrakterDatabaseManager adm = new KonkreterDatabaseManager(new KonkreteDataBase()); //Hier werde ich Konkret
   
    public static AbstrakterDatabaseManager getAbstrakterDatabaseManager()
    {
        return adm;
    }
}

Java:
public class DIAufrufExample
{
    public static void main (String[] args) throws DataAcessException
    {
        String input = "Test";
       
        UserData data = ApplicationContext.getAbstrakterDatabaseManager().getUserMail(input);
       
        System.out.println("Name: "+data.getUserName());
        System.out.println("eMail: "+data.getEmail());
    }
}
 

XyMorgan

Aktives Mitglied
Der gesamte DB-Kram kennt sich untereinander, was dabei nach ziemlichem Unsinn aussieht, und die Austauschbarkeit gegen "echte" Implementierungen auch gegen 0 gehen lässt...
Die Daos, über die ja die Daten völlig ohne Kenntnis der wirklichen Herkunft bereitstellen sollen, geben die Datenbank selber preis, und kennen auch noch den DatenBankManager, bieten aber als Interface gar nichts, um die Daten abzufragen...

@mrBrown Ich gehe mal davon aus, dass du dir nicht die Mühe gemacht hast den ganzen Beitrag zu lesen :)

Solution
Use a Data Access Object (DAO) to abstract and encapsulate all access to the data source. The DAO manages the connection with the data source to obtain and store data.

Quelle: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

@mrBrown Darüber hinaus ist dein Wissen über (Java) Design Patterns nicht sehr ausgeprägt. Vielleicht machst du dir die Mühe und liest mal das ein oder andere nach, bevor du hier fragwürdige Aussagen triffst. Den entscheidenden Text hab ich dir mal unterstrichen. Wenn du mit der verwendeten Sprache nicht so vertraut bist helfe ich gerne beim übersetzen.

@Meeresgott
Passt soweit ganz gut. Wobei ich jetzt nicht wirklich verstehe worum es genau geht. Ist es jetzt eine Übung, soll der Client direkt auf eine Datenbank zugreifen, oder wird es nachher Client-Server-DB?

Wenn es mehr als nur ausprobieren ist, dann würde ich im Hinblick auf den weiteren Ausbau den Manager etwas umstellen und die DAOs beim Manager registrieren, dann sparst das ewige Erweitern des Managers, müsst ja sonst nach und nach alle DAOs reinklöppeln.

Dazu macht ne Erweiterung deines KonkretenManagers -> UserDataenBankManger und packst in den Konkreten ne protected List<Dao> registeredDaos rein. Im konkreten machst dann die Instanz von der UserDao un addest die.
->
Java:
public void registerDao() {
      registeredDao.add(UserDao.class); // oder über super.registerDao(..) wenn du keine protected Variable willst in der Super-Klasse
}

Dann lässt später den KonkretenDatenBankManager die DAO erzeugen. Und packst noch die Methoden in das DatenBankManager Interface für registrieren und holen.
 

mrBrown

Super-Moderator
Mitarbeiter
Quelle: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

@mrBrown Darüber hinaus ist dein Wissen über (Java) Design Patterns nicht sehr ausgeprägt. Vielleicht machst du dir die Mühe und liest mal das ein oder andere nach, bevor du hier fragwürdige Aussagen triffst. Den entscheidenden Text hab ich dir mal unterstrichen. Wenn du mit der verwendeten Sprache nicht so vertraut bist helfe ich gerne beim übersetzen.

Solution
Use a Data Access Object (DAO) to abstract and encapsulate all access to the data source. The DAO manages the connection with the data source to obtain and store data.

Auch für dich mal der relevante Teil unterstrichen, und als Zusatz dein DAO-Interface:

Java:
public interface Dao {
    public DataBase getDataBase();
}

getDataBase als einzige Methode und "encapsulate all access to the data source" widersprechen sich in meinen Augen irgendwie, vllt ist das aber auch nur ein Pattern was ich nicht kenne ;)
 

XyMorgan

Aktives Mitglied
...vllt ist das aber auch nur ein Pattern was ich nicht kenne

@mrBrown Da würde ich dir 100% zustimmen.

getDataBase als einzige Methode und "encapsulate all access to the data source" widersprechen sich in meinen Augen irgendwie

Nein, konkret gibt es nur eine simple (Map)-DB (oben mal durchgelesen?), was soll da außer getDataBase() ins Interface, getMapConnectionToSimpleDataBase(), createPseudeSuperSQLStatementForSimpleMap(), convertSimpleObjectsToSomeWhatSUperObjectsFromMap()?

Denke @Meeresgott wäre für kreative Vorschläge dankbar ^^

Den Zugriff auf eine Datenquelle zu machen ohne Sie zu kennen dürfte recht schwer werden. Der Grund für das DAO-Pattern ist nicht tolle Klassen zu bauen, sondern einen Layer bereitzustellen, der Geschäftslogik von der Persistierung trennt, damit man den (kompletten!) DAO-Layer simple austauschen kann.

Da nicht klar ist, was Kollege @Meeresgott nun genau vor hat, könnte man noch über ConnectionDriven DAO oder ThreadDriven DAO statt DataBaseDriven sprechen, falls du mir folgen kannst :)

Das das Interface noch mit div. Nettigkeiten versehen werden kann, soll, muss ist wohl selbstredend, aber ich kann mich nicht erinnern, dass in der Hauptfrage des Beitrags eine Komplettlösung angefragt wurde.

Und wie ich bereits diverse male erwähnte, natürlich würde man später alle DAOs, Manager und DataBase injecten.

Ich mache zwar erst seit ca. 2 Wochen Java und diesen Anwendungsentwicklungskrams, hab aber ein schlaues Buch gelesen. Hoffe das hat mir geholfen.

In diesem Sinne, trotzdem Danke für deine Hilfe, ich glaube jetzt hab ich das Pattern wirklich verstanden.

//XyMorgan_
 

mrBrown

Super-Moderator
Mitarbeiter
Nein, konkret gibt es nur eine simple (Map)-DB (oben mal durchgelesen?), was soll da außer getDataBase() ins Interface, getMapConnectionToSimpleDataBase(), createPseudeSuperSQLStatementForSimpleMap(), convertSimpleObjectsToSomeWhatSUperObjectsFromMap()?
Gar nichts davon - aber eben auch kein getDataBase. ÜPber das Interface sollen schließlich Daten kommen, nicht die Datenbank. Das heißt nicht umsonst Data Access Object, und nicht DataBase Access Objekt.

Den Zugriff auf eine Datenquelle zu machen ohne Sie zu kennen dürfte recht schwer werden. Der Grund für das DAO-Pattern ist nicht tolle Klassen zu bauen, sondern einen Layer bereitzustellen, der Geschäftslogik von der Persistierung trennt, damit man den (kompletten!) DAO-Layer simple austauschen kann.
Innerhalb der DAOs muss die Datenbank bekannt sein, nach außen eben nicht. Wenn die Geschäftslogik von der Datenbank abhängt läuft irgendwas ziemlich schlief.
Bisher sind deine "DAOs" eben keine Layer über der Datenbank, sondern geben die Datenbank nach außen weiter.

Da nicht klar ist, was Kollege @Meeresgott nun genau vor hat, könnte man noch über ConnectionDriven DAO oder ThreadDriven DAO statt DataBaseDriven sprechen, falls du mir folgen kannst :)
Kann ich, ist aber alles ziemlicher Unsinn. Das alles ist Implementierungsdetail, und hat mit dem DAO-Interface nichts zu tun.
Das DAO soll eben genau davon abstrahieren.

Und wie ich bereits diverse male erwähnte, natürlich würde man später alle DAOs, Manager und DataBase injecten.
Was mit deiner Architektur nur schwerlich möglich ist.

Ich mache zwar erst seit ca. 2 Wochen Java und diesen Anwendungsentwicklungskrams, hab aber ein schlaues Buch gelesen. Hoffe das hat mir geholfen.
Erklärt so einiges...
 

Meeresgott

Bekanntes Mitglied
Ich merke schon es gibt mehrere Meinungen zur Umsetzung.

Mein Problem ist, dass ich einen Server habe (mit Datenbank) und einen Client mit GUI den Code dafür habe ich vor längerer Zeit geschrieben und als ich was verändern wollte bin ich fast ausgerastet da dieser sehr schlecht Strukturiert ist. Mein Hauptproblem ist es die Geschäftslogik von der GUI zu trennen.
Deshalb dachte ich, das ich in meinem Beispiel, dass ich zuerst in den Thread gepostet habe die Strecke Client <--> Server erstmal vernachlässige. Und habe somit ein Client DB Szenario erschaffen. Da ich dachte das ich eine Schnittstelle von der GUI zur Geschäftslogik einbaue und eine Schnittstelle von der Geschäftslogik zu Datenbank. Und das ich später die DB einfach ersetzte durch meine Connection.

Allerdings kam das hier
if(data instanceof ButtonEvent)
sehr schlecht an.

Da ich dieselbe Methode benutze um eine Client-, Serverkommunikation zu ermöglichen und mir keine Lösung eingefallen ist wie ich dieses Problem umgehe bzw löse. Wollte ich euch das auch noch fragen.

Habe mich aber anscheinend nicht sehr helle dabei angestellt und euch damit nur verwirrt.

Also die Frage des Threads war eigentlich hauptsächlich nach einer sauberen Schnittstelle zwischen GUI und Geschäftslogik.

Die Frage die später noch dazu kam war dann eine saubere Kommunikation zwischen Client und Server sowie von der Geschäftslogik eine Saubere Schnittstelle zur Connection (Am besten wäre es wenn man Sie so universel hinbekommt, dass es zum Beispiel per injecten möglich ist eine Connection zu einem Server(Standard Java Server), Einer Datenbank bei dem Client oder eine MySql Datenbank ist)

Viele Grüße
 

XyMorgan

Aktives Mitglied
<- gibt auf, @mrBrown du bist jetzt der neue Chefarchitekt :D


@thecain kurz da nach.....

All in all the general consensus is that it all depends on the application and requirements. Adam sums it up,

Quelle: https://www.infoq.com/news/2007/09/jpa-dao

... es gibt auch Experten die behaupten ab 2020 gibt es nur noch Elektroautos zu kaufen, mal schauen.
 

mrBrown

Super-Moderator
Mitarbeiter
Da ich dieselbe Methode benutze um eine Client-, Serverkommunikation zu ermöglichen und mir keine Lösung eingefallen ist wie ich dieses Problem umgehe bzw löse. Wollte ich euch das auch noch fragen.

Habe mich aber anscheinend nicht sehr helle dabei angestellt und euch damit nur verwirrt.

Also die Frage des Threads war eigentlich hauptsächlich nach einer sauberen Schnittstelle zwischen GUI und Geschäftslogik.

Mein Weg wäre, jegliche Eventbehandlung (zb waitOfUserEvent, getUserData) aus der GUI raus zu halten. Stattdessen eine passende Controller-Klasse, mit Methoden für jeden Button, welche du als ActionListener setzt.

UU hat es Sinn, noch eine ModelSchicht einzuführen, welche die von der View anzuzeigenden Daten bereit hält. Der Controller aktualisiert dann im Model die anzuzeigenden Daten, und dieses informiert die View (Observer/Listener-Pattern)

View<->Controller läuft dann rein über die ActionListener (welche man je nach Umstand noch hinter einem eigenem Interface für den Controller verstecken kann), die Kommunikation View<->Model nur über die Observer/Listener und die öffentlichen Schnittstellen des Models.


Die Frage die später noch dazu kam war dann eine saubere Kommunikation zwischen Client und Server sowie von der Geschäftslogik eine Saubere Schnittstelle zur Connection (Am besten wäre es wenn man Sie so universel hinbekommt, dass es zum Beispiel per injecten möglich ist eine Connection zu einem Server(Standard Java Server), Einer Datenbank bei dem Client oder eine MySql Datenbank ist)

Für die Schnittstelle zur "Datenbank" einfach ein Interface definieren (was man dann wenn man unbedingt will DAO nennen kann...), welches die nötigen Methoden zum abfragen/ändern der Daten beinhaltet, dazu dann eine Factory (oder das später übers DI-Framework machen lassen).
Diene bisherige DataBase-Klassse ist dann einfach nur eine Implementierung dieses Interfaces, die dir von der Factory zurückgegeben wird. (Das Grundlegende Design dafür gibts in dem Oracle-Artikel von @XyMorgan, du solltest dich da nur am Artikel, nicht an seiner Umsetzung orientieren ;))

Willst du's nachher austauschen gegen eine echte Datenbank implementiert du einfach das Interface neu, und lässt die Factory die neue Implementation zurückgeben.
 

Meeresgott

Bekanntes Mitglied
jegliche Eventbehandlung (zb waitOfUserEvent, getUserData) aus der GUI raus zu halten

So wie ich dich jetzt verstanden habe wäre ich wieder bei dem selbem Problem wie am Anfang.
Wenn ich der Meiner GUI-Klasse eine Methode hinzufüge mit addActionListener(MyGUIListener)
und MyGUIListener die Methode hat UserData;getUserData() muss ich doch erstmal irgenwie herausfinden welches Event jetzt eingetreten ist.

Später kann ich nochmal einen Code Entwurf schicken wie ich glaube es verstanden zu haben allerdings wäre dann das Interface sehr stark von der Gui abhängig :/

@XyMorgan Bei dem Pattern MVC habe ich doch das Problem das ich die view zwar setzen kann aber kein EventHandling betreiben kann. Zumindest so wie ich das MVC Muster verstanden habe.
 

mrBrown

Super-Moderator
Mitarbeiter
So wie ich dich jetzt verstanden habe wäre ich wieder bei dem selbem Problem wie am Anfang.
Wenn ich der Meiner GUI-Klasse eine Methode hinzufüge mit addActionListener(MyGUIListener)
und MyGUIListener die Methode hat UserData;getUserData() muss ich doch erstmal irgenwie herausfinden welches Event jetzt eingetreten ist.

Naja, du hast eine endliche Anzahl möglicher Events, kannst also für jedes Event eine Methode im Controller(-Interface) deklarieren, die sie behandelt.
Der GUI wird der Controller übergeben, die erstellt ActionListener, die die Methoden aufrufen. Entweder jeder Button seinen eigenen ActionListener, dann ist darüber die Zuweisung eindeutig, oder du vergleichst im ActionListener die Quelle des Events mit deinen Buttons und hast so die eindeutige Zuordnung.

Später kann ich nochmal einen Code Entwurf schicken wie ich glaube es verstanden zu haben allerdings wäre dann das Interface sehr stark von der Gui abhängig :/
Welches Interface ist von der GUI abhängig?
 

Meeresgott

Bekanntes Mitglied
Der Controller bekommt die GUI Instantz und der Controller gibt der GUI die ActionListener ?


Code:
public class Conrtoller implements ActionListener
{
    GUI gui;

    public Controller(GUI gui)
    {
            this.gui = gui;
            gui.addActionListener(this);      
    }
   
    public void actionPerformed(ActionEvent event)
   {
          if(gui.getLoginButton().equals(event.getSource())
                     gui.getNameField().setText("LoginButton");
          if else( gui.getLoginButton().equals(event.getSource())
                     //Do some other Stuff

    }
}
So in der Art ? Dann wäre dieser ActionListener Stark von der GUI Abhängig. Würde man dass als abtrakte Klasse schreiben würde dann die abstrakte Methode void loginPressesd() aufgerufen werden.

Welches Interface ist von der GUI abhängig
Keines ich hatte es zuerst so verstanden, dass der GUI alles übergeben wird und die Gui den Controller "bedient". Das hat sich aber erledigt.

Viele Grüße

P.S. Keine Garantie auf den Code konnte ihn jetzt nicht überprüfen.
 

mrBrown

Super-Moderator
Mitarbeiter
So in der Art ? Dann wäre dieser ActionListener Stark von der GUI Abhängig. Würde man dass als abtrakte Klasse schreiben würde dann die abstrakte Methode void loginPressesd() aufgerufen werden.
Besser, dein Controller bekommt ein eigenes von ActionListener unabhängiges Interface, und die Zuordnung Button->Methode machst du in der GUI.

Außerdem den Controller die GUI erstellen lassen (oder eine andere Klasse beides erstellen lassen), und der GUI dann den Controller übergeben ;)


Manchmal wenn ich irgendwo "Senior Java Developer" lese, wundert es mich gar nicht mehr, dass so schlechte Software existiert...
 

Meeresgott

Bekanntes Mitglied
Habe jetzt alles so umsetzten können wie ich es verstanden habe.


Java:
public interface Controller
{
    public void loginButtonPressed();
    public void registerButtonPressed();
}

Habe den build Teil rausgelassen. Wichtig ist ja nur das beide Buttons den MyActionListener adden.

Java:
public class GUI {

    private JFrame jframe;
   
    private JLabel userNameLabel;
    private JLabel emailLabel;
   
    private JButton loginButton;
    private JButton registerButton;
   
    private Controller controller;
   
    public void buildGUI()
    {
        // buid components
    }

    public void showGUI()
    {
        jframe.setVisible(true); 
    }

    public void setController(Controller controller)
    {
        this.controller = controller;
    }
   
    public class MyActionListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            if(loginButton.equals(e.getSource()))
                controller.loginButtonPressed();
            else if(registerButton.equals(e.getSource()))
                controller.registerButtonPressed();
        }
    }
}

und die konkrete implementierung von Controller

Java:
public class MyController implements Controller
{
    private GUI gui;
   
    public MyController(GUI gui)
    {
        this.gui = gui;
        gui.setController(this);
    }
    @Override
    public void loginButtonPressed()
    {
        //Was genau soll hier rein ?
    }
    @Override
    public void registerButtonPressed() {
       
    }
}

Zum letzten Teil hätte ich noch eine Frage. Ich hatte zu test zwecken das Login so gestaltet, dass wenn man einen in der Datenbank schon vorhandenen User ins Loginfeld tippt die eMail des jeweilgen users in einen TextField gezeigt wird (Einfach um einen Datenaustausch zu simulieren)

Wie wäre es am besten in die loginButtonPressed Methode getter zu verwenden
gui.getEMailField().setText("eMail");

Die GUI ebenfalls ein Interface gönnen und
gui.setEMail("eMail")
eine E-Mail Setter Methode so zu implementieren damit der Controller nicht mit Swing herumhantieren muss.
Oder dem Interface Controller der Methode "public void loginButtonPressed()"
den Rückgabe wert String geben und diesen dann in der GUI weiterzuverarbeiten --> Allerdings hätte man bei DB-Abfragen die etwas länger dauern einen Hänger in der GUI...

Was scheint hier am Sinnvlosten?
 

Meeresgott

Bekanntes Mitglied
Alles klar schien mir auch die Lösung zu sein.
Oder würde es Sinn machen eine abstrakte Klasse zu erstellen, die schon mit der Instanzvariable Controller ausgestattet ist ?

Dann denke ich mal dass in den Controller meine Instanz für die Datenbank kommt bzw. für den Client.

Dann wären alle GUI Fragen erledigt.
Allerdings bleibt eine frage noch offen wenn meine Verbindung zu Datenbank über den Server funktionieren soll wie mache ich das sauber mit der Abfrage was für eine Anfrage der Server bekommt.
Denn an dieser Stelle denke ich mal ist instanceof wieder nicht angebracht :/
 

mrBrown

Super-Moderator
Mitarbeiter
Wie meinst du das?
Welche Anfrage der Server bekommen muss ist doch aus der aufgerufenen Methode ersichtlich.

instanceof ist so ziemlich immer der falsche Weg ;)
 

Meeresgott

Bekanntes Mitglied
Also was ist besser einmal so:
Java:
public abstract class AbstraktGUI
{
    protected Controller controller;
 
    public void setController(Controller controller)
    {
        this.controller = controller;
    }
 
    public abstract void setText(String text);
    //Mehr Methoden
}
Oder so
Java:
public interface InterfaceGUI
{
    public void setController(Controller controller);
    public void setText(String txt);
}

was der Client an der Server sendet ist mehr als klar.
Nur verschicke ich Objekte an den Server und je nach Objekt castet er dieses zurück nimmt die Informationen aus dem Objekt erstellt ein Antwort Objekt und schickt dieses zurück an den Client.

Kann dir auch gerne ein Code Beispiel dafür geben aber ich sage dir gleich du wirst das nicht gut heißen
 

mrBrown

Super-Moderator
Mitarbeiter
Beides zusammen, das abstrakte implementiert das Interface ;)


Vor dem Cast brauchst du in jedem Fall instanceof, allerdings sollte das immer nur nötig sein, um keinen unchecked Cast zu haben, nicht, um zu entscheiden was zu tun ist ;)
Kannst aber ruhig mal Code zeigen
 

Meeresgott

Bekanntes Mitglied
So Simple und trotzdem gut. Warum komme ich nie selbst auf sowas :)

Hier wäre ein Beispiel für meinen ClientHandler für unseren Fall mit dem Login und Register

Java:
public class ClientHandlerExample implements Runnable
{
    private Socket socket;
    private ObjectInputStream in;
    private ObjectOutputStream out;
  
    private boolean run;
  
    public ClientHandlerExample(Socket s) throws IOException
    {
        this.socket = s;
        this.in = new ObjectInputStream(s.getInputStream());
        this.out = new ObjectOutputStream(s.getOutputStream());
        this.run = true;
    }
  
  
    @Override
    public void run()
    {
        while(run)
        {
            try
            {
                Object obj = in.readObject();
              
                if(obj instanceof LoginData)
                {
                    //mache etwas
                    LoginAnswerData data = Logik.getLoginAnswer((LoginData) obj);
                    out.writeObject(data);
                }
                else if( obj instanceof RegisterData)
                {
                    RegisterAnswerData data = Logik.getRegisterAnswer((RegisterData) obj);
                    out.writeObject(data);
                }//Und so weiter esso mehr Objekte desto länger das hier
              
            }
            catch (IOException | ClassNotFoundException ex)
            {
                Logger.getLogger(ClientHandlerExample.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
  
    public void close()
    {
        run = false;
        //close Connections
    }
  
}

Dieses instanceof hätte ich da gerne irgendwie weg zumindest nicht mehr für die Entscheidung wie du breits gesagt hast ;)
 

Meeresgott

Bekanntes Mitglied
Java:
public interface Controller
{
    public void loginButtonPressed();
    public void registerButtonPressed();
}

Doch noch eine letzte Frage die ich mir grade beim rumspielen mit diesem Code gestellt habe.
Ich brauche ja den Usernamen von loginButtonPressed() also muss ich die Methode ändern in loginButtonPressed(String username). Zumindest macht das so
 

mrBrown

Super-Moderator
Mitarbeiter
Dieses instanceof hätte ich da gerne irgendwie weg zumindest nicht mehr für die Entscheidung wie du breits gesagt hast
Was ginge wäre ein Wrapper um die Objekte, der jeweils Typ (als Enum|String|int etc) und das Objekt enthält. Auf Serverseite dann mit Switch/if-Orgie/ChainOfResponsibility/Map Typ prüfen und passend behandeln


Java:
public interface Controller
{
    public void loginButtonPressed();
    public void registerButtonPressed();
}

Doch noch eine letzte Frage die ich mir grade beim rumspielen mit diesem Code gestellt habe.
Ich brauche ja den Usernamen von loginButtonPressed() also muss ich die Methode ändern in loginButtonPressed(String username). Zumindest macht das so
Ja, kann man so machen, weniger getX ist immer gut
 

Meeresgott

Bekanntes Mitglied
Wrapper um die Objekte, der jeweils Typ (als Enum|String|int etc)

Habe mich jetzt ein bisschen umgeschaut. Allerdings konnte keinen Wrapper finden der ein Object und ein Integer aufnimmt ich konnte noch nicht mal einen Wrapper finden der ein Object aufnehmen kann. Noch nicht mal einen Ansatz wie man seinen eigenen Wrapper schreiben kann der ein Integer und ein Object aufnimmt :(

Okay gut dann habe ich zumindest das verstanden
 

mrBrown

Super-Moderator
Mitarbeiter
Einfach nur ein Objekt, was als Instanzvariablen ein Objekt und eben den Typ hat ;)

Fertig wirds sowas zumindest in java.x nicht geben, am ehesten als Tupel in irgendeine Apache Lib
 

Meeresgott

Bekanntes Mitglied
Schon wieder so einfach..
Hätte da jetzt zwei Ansätze für:

Java:
public class MyWrapper
{
    public static final int LOGIN_DATA = 0;
   
    private int value;
    private Object obj;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }
}

Oder so etwas:
Java:
public abstract class MyWrapper
{
    public static final int LOGIN_DATA = 0;
   
    private int value;
   
    public MyWrapper(int dataIndex)
    {
        this.value = dataIndex;
    }
   
    public int getValue()
    {
        return value;
    }
}

Java:
public class LoginData extends MyWrapper
{
    private String txt;
    //Noch mehr
   
    public LoginData(int dataIndex) {
        super(MyWrapper.LOGIN_DATA);
    }

    public String getTxt() {
        return txt;
    }

    public void setTxt(String txt) {
        this.txt = txt;
    }
    //Noch mehr
}

Was findest du besser ? beides würde den Zweck erfüllen.
 

Meeresgott

Bekanntes Mitglied
Beim umschreiben des Servers kam ich auf ein Problem.
Und zwar das ich vorher Prüfen muss ob es ein MyWrapper Object ist oder nicht um es zu Casten.

Habe es so gelöst, dass ich einen "eigenen" ObjectInputStream/OutputStream geschrieben haben und die Methoden writeWrapper(MyWrapper) bzw. MyWrapper;readWrapper() hinzugefügt habe und dort eine Abfrage gemacht habe mit instanceof und wenn das Object kein MyWrapper Object ist dann schmeißt der "WrapperOutputStream/InputStream" eine Exception.

Ist das dann eine korrekte Anwendung für instanceof ?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Best Practice Logik in der Datenbank oder in Java? Java Basics - Anfänger-Themen 3
H Tic Tac Toe Logik kürzer fassen Java Basics - Anfänger-Themen 8
I Logik Zahlungsprozess - Wann Bestellobjekt anlegen? Java Basics - Anfänger-Themen 2
H Logik Fehler erkennen Java Basics - Anfänger-Themen 21
M Kann mir jemand hier die Logik vermitteln? Java Basics - Anfänger-Themen 3
M Kann mir jemand die Logik erklären? Java Basics - Anfänger-Themen 1
Hias12345 Schach(Springer Logik) Java Basics - Anfänger-Themen 27
C Array-Werte werden gemischt, ohne Logik Java Basics - Anfänger-Themen 2
B Logik Upgrade / Downgrade Java Basics - Anfänger-Themen 13
I Hilfe bei der Logik Java Basics - Anfänger-Themen 9
A Minesweeper Logik Java Basics - Anfänger-Themen 10
D Logik von GUI trennen Java Basics - Anfänger-Themen 3
V Memory Logik Problem/Denkblockade, bitte helft Java Basics - Anfänger-Themen 1
Z Jump and Run - Grafik,Logik und GUI trennen Java Basics - Anfänger-Themen 4
P fibonacci - do while Statement Logik Fehler Java Basics - Anfänger-Themen 5
Z GUI und Logik - Trennung Java Basics - Anfänger-Themen 2
H Logik Frage Java Basics - Anfänger-Themen 3
X Methoden Logik-Problem mit Schleifen. Java Basics - Anfänger-Themen 7
kaoZ Logik und Gui trennen Java Basics - Anfänger-Themen 3
S Logik knobeln... Java Basics - Anfänger-Themen 4
G Klassen Von Logik auf TextField in der GUI zugreifen Java Basics - Anfänger-Themen 14
V Verstehe die Logik nicht ... Java Basics - Anfänger-Themen 30
S OOP Trennung der GUI von der Logik Java Basics - Anfänger-Themen 11
F While Schleife - Logik ? Java Basics - Anfänger-Themen 5
B Logik von verschachtelten For Schleifen Java Basics - Anfänger-Themen 6
Luk10 Logik/Mathe Problem Java Basics - Anfänger-Themen 6
M Logik in Java Java Basics - Anfänger-Themen 4
K java.util.ConcurrentModificationException problem in der Logik? Quaxli-Tutorial Java Basics - Anfänger-Themen 9
S Frage zu Verständnis und Logik Java Basics - Anfänger-Themen 5
K Logik in if-Bedingung Java Basics - Anfänger-Themen 2
L Wie Trennung von Logik und Ausgabe? Java Basics - Anfänger-Themen 6
T Hilfe - Ein Logik Problem Java Basics - Anfänger-Themen 17
sliwalker Wie löse ich eine "DfB-Pokalauslosung"?Logik fehlt Java Basics - Anfänger-Themen 5
T Problem mit der Logik von Switch und do-while Java Basics - Anfänger-Themen 3
G die Logik für eine Buchung! Java Basics - Anfänger-Themen 3
I Erste Schritte Einfache Datenbank-Webseite erstellen als Nicht-IT-lerin Java Basics - Anfänger-Themen 24
M Daten aus errechneter Methode in Datenbank(SQLite) schreiben Java Basics - Anfänger-Themen 60
S Best Practice Fragen zu Projektstruktur einer Datenbank-Abfrage-App (MVC) Java Basics - Anfänger-Themen 13
I Element n aus Datenbank Query (JPA / Hibernate) Java Basics - Anfänger-Themen 3
I Passwort in Datenbank speichern um später wieder auszulesen Java Basics - Anfänger-Themen 5
S OOP Java Eingabe in verschiedene Datenbank Tabellen eintragen Java Basics - Anfänger-Themen 7
I H2 Datenbank starten / Daten in File speichern Java Basics - Anfänger-Themen 25
E schneller von der Datenbank abfragen Java Basics - Anfänger-Themen 15
E Datenbank Spalte zusammenzählen Java Basics - Anfänger-Themen 2
R Datenbank Java Basics - Anfänger-Themen 1
I API Key´s in der Datenbank decrypt / encrypten? Java Basics - Anfänger-Themen 23
I Werte (u.a. Geldbeträge) in Datenbank speichern und Rundungen? Java Basics - Anfänger-Themen 8
M Mehrere Datenbank zugriffe über tomee.xml regeln? Java Basics - Anfänger-Themen 1
M Datenbank oder Textdatei? Java Basics - Anfänger-Themen 4
S Datenbank Befehl nach Login Java Basics - Anfänger-Themen 5
S Datenbank Tabelle eine Zeile an einer bestimmten Stelle einfügen Java Basics - Anfänger-Themen 2
M Von der Datenbank zum Textfield Java Basics - Anfänger-Themen 16
R Datenbank-Werte dynamisch ausgeben Java Basics - Anfänger-Themen 19
B Frage zu Datenbank Design - Rechnungen, Angebote... und deren Positionen Java Basics - Anfänger-Themen 4
B Datenbank: Entity mit vielen Referenzen? Ansatz so ok? Java Basics - Anfänger-Themen 8
T Datenbank | Welche am Sinnvollsten? Java Basics - Anfänger-Themen 5
S Daten speichern, ohne Datenbank Java Basics - Anfänger-Themen 8
L Daten aus ArrayList in Datenbank durchsuchen Java Basics - Anfänger-Themen 5
M Datenbank in jTable Laden Java Basics - Anfänger-Themen 49
M Datenbank verbindung Java Basics - Anfänger-Themen 19
J Java Verbindung mit mysql Datenbank Java Basics - Anfänger-Themen 3
B Datenbank, aktuelle Ende als Zahl an Label übergeben Java Basics - Anfänger-Themen 7
T Collections Geeignete Collection/Liste/Datenbank Java Basics - Anfänger-Themen 17
B Treetable (rekursive Funktion) aufbauen von Datenbank Java Basics - Anfänger-Themen 4
R Input/Output Verbindung mit mySql-Datenbank Java Basics - Anfänger-Themen 9
D Compiler-Fehler Wert auf Datenbank übertragen und Sleep Thread Java Basics - Anfänger-Themen 3
N (Java) Regristrierung und Login System mit einer Datenbank Java Basics - Anfänger-Themen 5
J Datenbank Zugriff Java Basics - Anfänger-Themen 24
J Mit JSF Formular in Datenbank schreiben Java Basics - Anfänger-Themen 3
DaCrazyJavaExpert Verschiede Aktionen der Datenbank getrennt durchführen Java Basics - Anfänger-Themen 4
DaCrazyJavaExpert Datenbank wird nicht erstellt Java Basics - Anfänger-Themen 31
E Daten gehen nicht in Datenbank Java Basics - Anfänger-Themen 14
C JTable update mit MySQL Datenbank Java Basics - Anfänger-Themen 1
B Schreiben von zu vielen Einträgen in einer Datenbank Java Basics - Anfänger-Themen 9
S Datenbank auf Knopfdruck abfragen Java Basics - Anfänger-Themen 8
M Java als Webanwendung mit Datenbank abfrage Java Basics - Anfänger-Themen 3
N Datenbank mit GUI verbinden - Wie? Java Basics - Anfänger-Themen 5
1 Datenbank in Java Java Basics - Anfänger-Themen 1
M Erste Schritte Java Applet - HTML Seiten auslesen und in Access Datenbank schreiben? Java Basics - Anfänger-Themen 15
J Bücher Datenbank Java Basics - Anfänger-Themen 5
S Best Practice MVC und große Datenmengen aus einer mySQL - Datenbank Java Basics - Anfänger-Themen 24
J Datum und Uhrzeit in Datenbank falsch hinterlegt Java Basics - Anfänger-Themen 13
R Erstversuch Datenbank Java Basics - Anfänger-Themen 6
I Daten speichern ohne Datenbank Java Basics - Anfänger-Themen 20
A Erste Schritte Verbindung zu MySQL Datenbank herstellen Java Basics - Anfänger-Themen 7
T Sql Datenbank - variable übergeben? Java Basics - Anfänger-Themen 8
C Passwörter möglichst sicher in Datenbank speichern Java Basics - Anfänger-Themen 18
W Erste Schritte Exceltabelle in Datenbank übertragen mittels XDEV Java Basics - Anfänger-Themen 7
J GUI mit phpMyAdmin Datenbank verbinden Java Basics - Anfänger-Themen 0
K Erste Schritte Datenbank SQL erklärung Java Basics - Anfänger-Themen 15
B Lokale Datenbank Java Java Basics - Anfänger-Themen 2
B Klassen Doppelte werte Filtern XML, Datenbank und DOM Java Basics - Anfänger-Themen 3
Todesbote Int Array mit Hibernate in Datenbank speichern. Java Basics - Anfänger-Themen 2
U Datenbank in Java Java Basics - Anfänger-Themen 8
M Keine Datenbank verbindung Java Basics - Anfänger-Themen 14
N mit Werten aus einer mysql datenbank in java rechnen Java Basics - Anfänger-Themen 17
Q Datenbank nicht über separaten Server Java Basics - Anfänger-Themen 4
B Dateiname in Datenbank schreiben Java Basics - Anfänger-Themen 2
J fortlaufende Objekte durch Variable auswählen; Datenbank Java Basics - Anfänger-Themen 4
S ArrayList in mysql Datenbank speichern Java Basics - Anfänger-Themen 6

Ähnliche Java Themen

Neue Themen


Oben