Pattern question

C

cantabile

Hi,

I'm trying to write a small installer for a server. But this program
should be able to run in the future under heterogenous environments and
os (at least linux/windows). I mean, the install will be done either in
text mode or curses or gtk or tk, either in debian or windows 2000 and
so on...

The idea, at the moment, is as follows :

class Server:
def __init__(self, params = None):
self.params = params
def __getattr__(self, attr):
return self.params.get(attr, None)

class Installer:
def __init__(self, gui = None):
self.gui = gui
self.srv = None

def update(self, dict):
self.srv = Server(dict)

class Gui:
def __init__(self, installer = None):
self.installer = installer
def main():
## Some stuff here calling doIt() when the
## user is done with filling various fields

def doIt(self):
dict = {"param1":"qwerty", "param2":"uiop"}
self.installer.update(dict)

def main():
inst = Installer()
gui = Gui(inst)
inst.gui = gui
inst.gui.main()

## Here will be the actual install method
## ...

## An example of accessing srv values:
print inst.srv.param1, inst.srv.param2

But, considering this code, I find the 3 first lines of my main() a bit
heavy. I have to inform inst that it has a 'gui', and Gui that it has an
'installer'. I was trying to implement something looking like (very
roughly) to the Observer pattern (so that the Gui would be totally
independant from the actual install process).
I guess there is something wrong in my approach. Is there a better
pattern than this one for that kind of stuff ?

Tanks for your help.
 
B

bruno modulix

cantabile said:
Hi,

I'm trying to write a small installer for a server. But this program
should be able to run in the future under heterogenous environments and
os (at least linux/windows). I mean, the install will be done either in
text mode or curses or gtk or tk, either in debian or windows 2000 and
so on...

The idea, at the moment, is as follows :

class Server:
def __init__(self, params = None):
self.params = params
def __getattr__(self, attr):
return self.params.get(attr, None)

class Installer:
def __init__(self, gui = None):
self.gui = gui
self.srv = None

def update(self, dict):
self.srv = Server(dict)

class Gui:
def __init__(self, installer = None):
self.installer = installer
def main():
## Some stuff here calling doIt() when the
## user is done with filling various fields

def doIt(self):
dict = {"param1":"qwerty", "param2":"uiop"}
self.installer.update(dict)

def main():
inst = Installer()
gui = Gui(inst)
inst.gui = gui
inst.gui.main()

## Here will be the actual install method
## ...

## An example of accessing srv values:
print inst.srv.param1, inst.srv.param2

But, considering this code, I find the 3 first lines of my main() a bit
heavy. I have to inform inst that it has a 'gui', and Gui that it has an
'installer'. I was trying to implement something looking like (very
roughly) to the Observer pattern (so that the Gui would be totally
independant from the actual install process).
I guess there is something wrong in my approach. Is there a better
pattern than this one for that kind of stuff ?

Tanks for your help.

You may want to have a look at the Factory pattern...

# outrageously oversimplified dummy exemple
class Gui(object):
def __init__(self, installer):
self.installer = installer

class PosixGui(Gui):
pass

class Win32Gui(Gui):
pass

class GuiFactory(object):
def getGui(self, installer):
if os.name == 'posix':
return PosixGui(installer)
elif os.name == 'win32':
return Win32Gui(installer)
else:
raise "os %s not supported" % os.name

class Installer(object):
def __init__(self, guiFactory):
self.gui = guiFactory.getGui(self)

def main():
inst = Installer(GuiFactory())
return inst.gui.main()

NB 1:
You may want to hide away the gui stuff:

class Installer(object):
def __init__(self):
self.gui = GuiFactory().getGui(self)

def main(self):
return self.gui.main()

def main():
return Installer().main()


NB 2 :
if it has to run in text mode, you should consider renaming "gui" to
"ui", since a CLI is not really a 'graphical' ui !-)

NB 3 :
I made the GuiFactory a class, but it could also be a simple function.

NB 4 :
there are of course other solutions to the problem, which may or not be
more appropriate...


HTH
 
C

cantabile

bruno modulix a écrit :
You may want to have a look at the Factory pattern...

# outrageously oversimplified dummy exemple
class Gui(object):
def __init__(self, installer):
self.installer = installer

class PosixGui(Gui):
pass

class Win32Gui(Gui):
pass

class GuiFactory(object):
def getGui(self, installer):
if os.name == 'posix':
return PosixGui(installer)
elif os.name == 'win32':
return Win32Gui(installer)
else:
raise "os %s not supported" % os.name

class Installer(object):
def __init__(self, guiFactory):
self.gui = guiFactory.getGui(self)

def main():
inst = Installer(GuiFactory())
return inst.gui.main()

NB 1:
You may want to hide away the gui stuff:

class Installer(object):
def __init__(self):
self.gui = GuiFactory().getGui(self)

def main(self):
return self.gui.main()

def main():
return Installer().main()

Thanks for this, Bruno. It is much more elegant and adaptable than my
first attempt.
NB 2 :
if it has to run in text mode, you should consider renaming "gui" to
"ui", since a CLI is not really a 'graphical' ui !-)

You're right :))
NB 3 :
I made the GuiFactory a class, but it could also be a simple function.
NB 4 :
there are of course other solutions to the problem, which may or not be
more appropriate...

Thanks a lot for these detailed explanations.
 
S

Scott David Daniels

cantabile said:
bruno modulix a écrit :

Taking advantage of Python's dynamic nature, you could simply:
# similarly outrageously oversimplified dummy example
class Gui(object):
def __init__(self, installer):
self.installer = installer

class PosixGui(Gui):
pass

class Win32Gui(Gui):
pass

if os.name == 'posix':
makeGui = PosixGui
elif os.name == 'win32':
makeGui = Win32Gui
else:
raise "os %s not supported" % os.name


class Installer(object):
def __init__(self, guiFactory):
self.gui = guiFactory(self)

def main():
inst = Installer(makeGui)
return inst.gui.main()

--Scott David Daniels
(e-mail address removed)
 
C

cantabile

Scott David Daniels a écrit :
Taking advantage of Python's dynamic nature, you could simply:
# similarly outrageously oversimplified dummy example
class Gui(object):
def __init__(self, installer):
self.installer = installer

class PosixGui(Gui):
pass

class Win32Gui(Gui):
pass

if os.name == 'posix':
makeGui = PosixGui
elif os.name == 'win32':
makeGui = Win32Gui
else:
raise "os %s not supported" % os.name


class Installer(object):
def __init__(self, guiFactory):
self.gui = guiFactory(self)

def main():
inst = Installer(makeGui)
return inst.gui.main()

--Scott David Daniels
(e-mail address removed)

Thank you too for this tip. :)
Coming from C++ (mainly), I'm not used to this dynamic way of doing
things. That's usefull.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,261
Messages
2,571,308
Members
47,976
Latest member
AlanaKeech

Latest Threads

Top