Seite 1 von 1

bidirektionale Klassen

Verfasst: Mittwoch 18. Januar 2006, 19:19
von george
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

Verfasst: Mittwoch 18. Januar 2006, 19:24
von modelnine
Ü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.

Verfasst: Mittwoch 18. Januar 2006, 19:36
von george
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

Verfasst: Mittwoch 18. Januar 2006, 19:46
von modelnine
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.

Verfasst: Mittwoch 18. Januar 2006, 20:07
von george
Hallo modelnine,

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


Gruss george

Verfasst: Mittwoch 18. Januar 2006, 20:16
von modelnine
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/ ... erfaces.py

(oder als markup: http://svn.asta.mh-hannover.de/viewcvs/ ... iew=markup)

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

--- Heiko.