bidirektionale Klassen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
george
User
Beiträge: 109
Registriert: Mittwoch 11. Januar 2006, 20:28
Wohnort: Berlin

bidirektionale Klassen

Beitragvon george » Mittwoch 18. Januar 2006, 19:19

Hallo,

welche Möglichkeiten gibt es, bidirektionale Klassenkommunikation zu ermöglichen.
Ich habe verschiedene Klassen, die durch einen Handler verwaltet werden.

ClassWork1
/ \
|
|
\ /
ClassHandler<----->ClassGUI
/ \
|
|
|
\ /
ClassWork2

Alle Klassen sollen nur über den Handler kommunizieren können.
Möchte also "ClassWork1" Funktionalität aus "ClassWork2" nutzen, muss dies über einen Aufruf im "ClassHandler" geschehen.
Wie implementiert man so eine Architektur?
Aus meiner Sicht müßte "ClassHandler" "ClassWork1" importieren und "ClassWork1" müßte "ClassHandler" importieren.
Das Problem ist aber, dass man dann aus der Klasse "ClassWork1" nicht die selbe Klasseninstanz von "ClassHandler" hat. Dies bedeutet, man hat unterschiedliche "ClassHandler"-Objekte und damit geht die Eindeutigkeit verloren.
Wie lößt man sowas sauber? Übergibt man beim Konstruktor-Aufruf von "ClassWork1" eine Variable, die auf den "ClassHandler" zeigt????
Sollte die von mir gewählte Architektur unsauber sein, wäre ich auch für Alternativen dankbar.
Danke.

george
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Beitragvon modelnine » Mittwoch 18. Januar 2006, 19:24

Übergibt man beim Konstruktor-Aufruf von "ClassWork1" eine Variable, die auf den "ClassHandler" zeigt?


Ja. Das ist eine saubere Lösung, indem Du zum Beispiel im ClassHandler selbst die Klasse ClassWork1 instantiierst, und bei der instantiierung self mitgibst.

Unabhängig davon: bist Du Dir sicher dass Du es so machen willst? Das ist eigentlich keine typische Python-Herangehensweise, weil man im Endeffekt in ClassHandler alles duplizieren muß wenn ClassWork1 mit ClassWork2 mit ... reden will. Warum nicht eine Klasse von ClassWork1 _und_ ClassWork2 ableiten und die dann ClassHandler nennen? Das ganze nennt sich in Python der Mixin-Pattern...

--- Heiko.
george
User
Beiträge: 109
Registriert: Mittwoch 11. Januar 2006, 20:28
Wohnort: Berlin

Beitragvon george » Mittwoch 18. Januar 2006, 19:36

Hallo modelnine,

Unabhängig davon: bist Du Dir sicher dass Du es so machen willst? Das ist eigentlich keine typische Python-Herangehensweise, weil man im Endeffekt in ClassHandler alles duplizieren muß wenn ClassWork1 mit ClassWork2 mit ... reden will. Warum nicht eine Klasse von ClassWork1 _und_ ClassWork2 ableiten und die dann ClassHandler nennen?


Das hatte ich auch erst überlegt. Das Problem ist aber, dass die einzelnen Klassen Hardware softwaremäßig darstellen. Es soll eine Möglichkeit geschaffen werden, schnell und einfach (modular) Klassen (sprich Hardwarekomponenten) zu nutzen.
Die Klassen sollen im Laufe der nächsten Zeit stark erweitert werden. Aus diesem Grunde habe ich von vornherein eine strikte Trennung gewählt.
Aus meiner Sicht war dies die bessere Lösung.
Danke

george
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Beitragvon modelnine » Mittwoch 18. Januar 2006, 19:46

Also im Endeffekt geht's darum dass jemand aus 'ner GUI eine neue Klasse an den ClassHandler ranhängen kann, und zwar schnell und problemlos?

Wenn dem so ist kann ich Dir eigentlich nur empfehlen irgendein Interfaces-Paket zu benutzen. Dann kannst Du die Hauptklasse als sowas wie einen Dispatcher schreiben, dem ein Klassenobjekt gegeben wird was er instantiieren soll (also eine Hardware an den dispatcher binden bindet automatisch den Dispatcher an die Hardware), und wenn eine Hardware/Klasse mit einer anderen Kommunizieren will, dass sie dann den Dispatcher fragt nach der Klasse die xyz implementiert.

Kleines Beispiel mit meiner Interfaces-Klasse (nicht getestet!!, sollte aber in dieser oder ähnlicher Form gehen):

Code: Alles auswählen

from Interfaces import *

class IVideoCard(Interface):

    def writeVideo(self,data):
        pass

class IRAM(Interface):

    def writeData(self,data):
        pass

class VideoCard(Implementor):
    provides(IVideoCard)

    def __init__(self,dispatcher):
        self._dispatcher = dispatcher

    def writeVideo(self,data):
        ram = self._dispatcher.getImplementor(IRAM)
        print "Dispatching to:", ram
        ram.writeData(data)

class RAM(Implementor):
    provides(IRAM)

    def __init__(self,dispatcher):
        self._dispatcher = dispatcher

    def writeData(self,data):
        print "Was dispatched to me:", data

class Dispatcher(object):
    def __init__(self):
        self._classlist = []

    def addClass(self,cls):
        self._classlist.append(cls(self))

    def getImplementor(self,iface):
        for inst in self._classlist:
            if inst.provides(iface):
                return inst
        raise KeyError

x = Dispatcher()
x.addClass(VideoCard)
x.addClass(RAM)

x.getImplementor(IVideoCard).writeVideo("test")


HTH!

Kleines PS: getImplementor() ist extrem ineffizient implementiert. Das ganze könnte man auf jeden Fall schöner machen indem man ein Dict mit den Interfaces:Instanz-Mappings verwaltet. Das geht, müßte ich aber in Interfaces noch vorsehen dass man direkt auf die Interface-Liste zugreifen kann um so einen dict zu erstellen wenn ein neues Modul eingehängt wird.

--- Heiko.
Zuletzt geändert von modelnine am Mittwoch 18. Januar 2006, 20:17, insgesamt 1-mal geändert.
george
User
Beiträge: 109
Registriert: Mittwoch 11. Januar 2006, 20:28
Wohnort: Berlin

Beitragvon george » Mittwoch 18. Januar 2006, 20:07

Hallo modelnine,

das sieht nicht schlecht aus.
Werde es mal in Ruhe durcharbeiten und probieren.
Danke dir.


Gruss george
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Beitragvon modelnine » Mittwoch 18. Januar 2006, 20:16

Wenn Du damit wirklich rumspielen willst brauchst Du noch irgendein Modul was für Python Interfaces implementiert. Da gibts 'ne ganze Menge (z.B. ZopeInterfaces, PyInterfaces), und unter anderem auch meine Implementierung:

http://svn.asta.mh-hannover.de/viewcvs/PyAsync/trunk/core/interfaces/Interfaces.py

(oder als markup: http://svn.asta.mh-hannover.de/viewcvs/PyAsync/trunk/core/interfaces/Interfaces.py?rev=214&view=markup)

Ich persönlich fand ZopeInterfaces bzw. PyInterfaces immer etwas restriktiv (und hab deswegen meine eigene Implementierung von Interfaces geschrieben), aber YMMV.

--- Heiko.

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot], r.barrios