# Abstractes/Schnittstellen für Objekte



## sTaX (28. Jul 2011)

Hi,

ich habe im "Hintergrund" ein System, welches Daten entgegen nimmt und diese intern verarbeitet.

Diese Daten können u.a. per HTTP-Request reinkommen. Aber auch andere Wege sollen möglich sein.

Ich habe natürlich auch ein paar Klassen mit Eigenschaften usw. Diese Eigenschaften möchte ich nun immer auf den richtigen Weg aufbereiten und das das Hintergrundsystem schicken. z.B. per HTTP-Request.

Allerdings weiß ich nicht, wie ich dies elegant designen kann. Ich habe mir gedacht, dass z.B. eine Connector-interface mit einer "create()" Methode erstellen kann und davon dann Unterklassen "HTTPConnector" usw.

Meine eigentlichen Klassen mit den Eigenschaften sollten dann z.B. HTTPConnector impementieren.
Dann müsste ich natürlich die create()-Methode auf den "HTTP-Fall" anpassen.

Was ist aber nun wenn ich von HTTP auf einen CAN-Bus wechseln möchte? Dann muss ich alle create()-Methoden löschen bzw neu erstellen. "Schnell mal hin und her" wechseln klappt dann nicht. Ich müsste dann immer einen Teil vom Code auskommentiert haben?!

Ein anderer Weg, der mir einfällt wäre das ich in den HTTPConnector eine Methode ala "create(MeineKlasse mk)" schreibe und das halt mehrmals und für jede einzelne Klasse dann einen angepassten Methodenrumpf.

Dies kommt mir aber nicht sonderlich elegeant vor, da die Klassen-Logik dann teilweise im HTTPConnector landet..

Ich hoffe Ihr konntet verstehen was ich meinte...


Sehr allgemein ausgedrückt:
Ich will Objekt A,B,C (jeweils unterschiedliche Klassen) über verschiedene Schnittestellen (HTTP,CAN,..) speichern.


----------



## SlaterB (28. Jul 2011)

ich verstehe es nicht wirklich, besondern nicht den Teil mit Methoden löschen/ anpassen/ Code auskommentieren,
Interface und Co gibt es doch gerade um komfortabel Objekte auszutauschen statt etwa if/else im Code oder schlimmeres,

wenn eine andere Implementation einer Methode benötigt wird, dann genau das Objekt wechseln, nicht irgendwas im Code,
wenn der Wechsel mitten in einer Methode stattfindet, dann läuft was falsch, dann muss der Ablauf in mehr Untermethoden aufgeteilt werden,

im Extremfall die aktuelle Methode per Exception oder return abgebrochen werden 
+ eine obere Instanz sorgt dafür dass es in einem anderen jetzt besser geeigneten Objekt (desselben Interfaces) weitergeht


----------



## sTaX (28. Jul 2011)

Okay, dann versuche ich es nochmal einfacher zu beschreiben:

```
public class EineDatenKlasse {
private String a;
private String b;
...
}

public class EineWeitereDatenKlasse {
private c;
private a;
...
}

public class HTTPConnector {
    public create(EineDatenKlasse o) {
        String requestString = "?test="+o.getA()+"&test2="+o.getB();
    }
    public create(EineWeitereDatenKlasse o) {
        String requestString = "?arg1="+o.getC()+"&arg2="+o.getA();
    }
}
```

Dies wäre jetzt ein Ansatz von mir. Allerdings finde ich den nicht sonderlich schön... Gibts da bessere Beispiele?


----------



## Marco13 (28. Jul 2011)

Theoretisch könnte man da wohl was mit Reflection machen, aber ... das sollte man nicht so unreflektiert empfehlen. Alle Methoden für alles Klassen in einer "HTTPConnector"-Klasse unterzubringen ist in der Tat unschön und schlecht erweiterbar. Aber ganz pragmatisch:
- Der request-String hängt von der Klasse ab
- Der request-String (bzw. ob überhaupt ein Request-String verwendet wird) hängt davon ab, ob es ein HTTPConnector ist.
Das sind zwei "orthogonale" Aspekte. Man wird also (ohne Reflection & Co) kaum drumrumkommen, für jede Kombination aus "Connector" und "Klasse" eine Methode zu schreiben. Flexibler wäre es aber vermutlich, wenn man diese Methoden in einzelne Klassen packen würde. 
Mit ist noch nicht klar, WAS mit dem "requestString" dann WO genau gemacht wird, und wie ein anderer Connector aussehen würde. Deswegen ist es schwer, da konkreter zu werden.


----------



## SlaterB (28. Jul 2011)

ich sehe da keinen Bezug/ kein Problem hinsichtlich Schnittstellen,

geht es dir jetzt um den vielen Request-Parameter-Code für möglicherweise beliebig viele Klassen?
das wäre eine andere Art Problem,
dagegen helfen vielleicht Reflection-Ansätze um alle über alle Attribute zu iterieren, oder direkter selber gebaut: 
in der Klasse keine normalen Parameter verwenden sondern eine Liste/ Map der Attribute mit Namen + vielleicht Zusatzinformationen wie den Namen des RequestParameters, 
diese letzte Info hat vielleicht in der Klasse an sich nichts zu sagen, könnte dann an anderer Stelle konzentriert abgelegt werden,
aber ohne dass die Info irgendwo einzeln vorhanden ist gehts nun mal kaum


----------



## sTaX (28. Jul 2011)

Dieser HTTP-Request-String wird dann an einen Webserver geschickt (nur bei HTTP).

Wenn es eine USART-Schnittstelle geben würde, dann werden die Daten seriell über einen COM-Port rausgeschickt.

Ich weiß jetzt auch nicht, wie man diese Schnittstelle verallgemeinern könnte...

z.B. in dem man sagt die normalen Klassen müssen alle das Interface "IHTTPConnector" implementieren.

Wenn ich dann von HTTP auf z.B. USART wechsle, muss ich ja den Methoden löschen/auskommentieren und die neue Logik hineinschreiben. Ziemlich unschön?!


Im Endeffekt will ich den Klassen "EineDatenKlasse" und "EineWeitereDatenKlasse" von außen über einen Methodenaufruf (immer der gleiche) sagen "Speichere dich". Wie er dann gespeichert wird (HTTP, USART, CAN,...) soll dann entschieden werden...


----------



## Marco13 (28. Jul 2011)

ALLE Klassen irgendwelche Interfaces wie "IHTTPConnectable" oder so implementieren zu lassen wäre in der Tat unsinnig. Im Moment steht in dem HTTPConnector ja nur, wie die Strings gebaut werden. Ohne die Details in aller Tiefe verstanden zu haben, könnte ein GANZ GROB skizzierter Ansatz vielleicht sowas sein wie

```
class HTTPConnector implements Connector
{
    private Map<Class<?>, HTTPEncoder> encoders ...

    @Override // von Connector
    public void sendObject(Object object)
    {
        HHTPEncoder encoder = encoders.get(object.getClass());
        String s = encoder.createString(object);
        send(s);
    }
}

class MeineKlasseEncoder implements HTTPEncoder
{
    String createString(Object object) { .... }
}

// Registrieren des Encoders:
httpConnector.register(MeineKlasse.class, new MeineKlasseEncoder());
```

Wirklich NUR GANZ GROB...


----------



## Ariol (1. Aug 2011)

Wie wäre denn sowas?

```
public void create(Object o) {
        String requestString = getRequestString(o);
        //....
    }

    public String getRequestString(Object o)
    {
    	if(o instanceof EineDatenKlasse)
    		return "?test="+((EineDatenKlasse)o.getA())+"&test2="+((EineDatenKlasse)o.getB());

    	if(o instanceof EineWeitereDatenKlasse)
    		return "?test="+((EineWeitereDatenKlasse)o.getC())+"&test2="+((EineWeitereDatenKlasse)o.getA());
    	
    	return "";    	
    }
```

Nicht wirklich viel Unterschied, ...


----------



## Marco13 (1. Aug 2011)

Man sollte IMHO instanceof vermeiden, bzw. IMMER, wenn man es verwendet, überlegen, ob das nicht ein Fall für Polymorphie wäre. Das Problem ist, dass jede Stelle, wo es verwendet wird, erneut angefasst werden muss, wenn es eine weitere Implementierung davon gibt...


----------

