jueves, 25 de septiembre de 2008

PATRONES ESTRUCTURALES (I). Patrón Adapter

El patrón Adapter proporciona un interface de una clase para otra que en circunstacias normales
sería incompatible. El adaptador convierte llamadas a su propio interface en llamadas al interface
original, por lo que se reduce la cantidad y complejidad del código para realizar la adaptación.
Este patrón también recibe el nombre de Wrapper (traducido al español envoltorio).

Dentro del patrón Adapter se pueden diferenciar dos casos:

  • El objeto Adapter. En este caso, lo que utiliza es una relación de asociación entre el Adaptador y el objeto adaptado.
  • La clase Adapter. La clase Adapter utiliza la herencia múltiple existente en algunos lenguajes como C++ o python o una herencia simple con una implementación de un interfaz como se realizaría en Java.
A continuación, os presento un ejemplo de la clase Adapter. Este ejemplo está basado en el funcionamiento del comando tar utilizado ampliamente en el mundo *NIX. Por defecto, este comando crea un fichero que contiene todos los archivos especificados en su entrada en la unidad de cinta predeterminada del sistema. Funcionaría de forma similar a los programas "zip" existentes pero sin comprimir, algo así como un fichero iso.

La característica que queremos remarcar aquí, es que por defecto el archivo se escribe en la unidad de cinta en vez de en el disco como es habitual en nuestros días. En principio podríamos pensar que un dispositivo de cinta es diferente de un dispositivo de disco por lo que crearemos una clase que adapte el interfaz existente para la unidad de cinta al funcionamiento de un interfaz de disco. Espero que el ejemplo sea lo suficientemente claro y que no se vea complicado por el ejemplo que se me ha ocurrido para ilustrarlo.



class Cinta(object):
def Escribir(self):
print "Escribiendo a cinta ..."
class Disco(object):
def EscribirADisco(self):
print "Escribiendo a disco ..."
class AdaptadorDiscoCinta(Cinta, Disco):
def Escribir(self):
self.EscribirADisco()

class MiTar(object):
handler = None
def __init__(self, param):
if param == "disco":
self.handler = AdaptadorDiscoCinta()
else:
self.handler = Cinta()
def backup(self):
self.handler.Escribir()

t = MiTar("")
t.backup()

t2 = MiTar("")
t2.backup()

domingo, 21 de septiembre de 2008

PATRONES CREACIONALES (III). Patrón Factory Method

El patrón Factory es una simplificación del patrón Abstract Factory.






#Patron Factory Method
class Vehiculo(object):
num_ruedas = 0
tipo_vehiculo = None

def __init__(self, nruedas):
self.num_ruedas = nruedas

def getNumRuedas(self):
return self.num_ruedas

def getTipoVehiculo(self):
return tipo_vehiculo

class Automovil(Vehiculo):
def getTipoVehiculo(self):
return "Automovil"

def setTipoMotor(tMotor):
self.tipo_motor = tMotor

class Motocicleta(Vehiculo):
def getTipoVehiculo(self):
return "Motocicleta"

def setCilindrada(nCilindrada):
self.num_cilindrada = nCilindrada

class FactoriaVehiculo(object):
def getVehiculo(self, nruedas):
if nruedas == 4:
return FactoriaAutomovil().getVehiculo()
else:
return FactoriaMotocicleta().getVehiculo()

class FactoriaAutomovil(FactoriaVehiculo):
def getVehiculo(self):
return Automovil(4)

class FactoriaMotocicleta(FactoriaVehiculo):
def getVehiculo(self):
return Motocicleta(2)

f = FactoriaVehiculo()
v = f.getVehiculo(2)

print v.getTipoVehiculo()
print v.getNumRuedas()


A continuación, enlazo un vídeo que he encontrado sobre este patrón del mismo autor que los anteriores.

sábado, 20 de septiembre de 2008

PATRONES CREACIONALES (II). Patrón Abstract Factory


El patrón de diseño Abstract Factory se utiliza para crear diferentes familias de productos.
Pudiéndose añadir nuevas familias en un futuro.



A continuación, presentamos un ejemplo típico del patrón Abstract Factory para la creación
de ventanas y botones en dos entornos gráficos diferentes WxWindows y Tkinter. Como hemos comentado
anteriormente este patrón está especialmente indicado cuando pueden aparecer nuevas familias
a las cuales dar soporte. En nuestro ejemplo, el caso típico sería incluir una nueva librería
gráfica como pyGTK.


#Abstract Factory Implementation
import Tkinter
import wx

class AbstractFactory(object):
app = None
def getFactory(self, library):
return {'Tkinter': TkinterFactory(), 'Wx': WxFactory()}[library]

def createApp(self):
raise NotImplementedError

def createWindow(self, parent,title):
raise NotImplementedError

def createButton(self, parent,title):
raise NotImplementedError

class TkinterFactory(AbstractFactory):
def createApp(self):
self.app = Tkinter.Tk()
return self.app

def createWindow(self, parent,title):
return TkinterWindow().createWindow(parent, title)

def createButton(self, parent,title):
return TkinterButton().createButton(parent, title)

def run(self):
self.app.mainloop()

class WxFactory(AbstractFactory):
def createApp(self):
self.app = wx.PySimpleApp()
return self.app

def createWindow(self, parent,title):
return WxWindow().createWindow(parent, title)

def createButton(self, parent,title):
return WxButton().createButton(parent, title)

def run(self):
self.app.MainLoop()

class AbstractWindow(object):
hnd = None
def createWindow(self, parent,title):
pass

class TkinterWindow(AbstractWindow):
def createWindow(self, parent,title):
self.hnd = Tkinter.Frame(parent)
parent.title(title)
self.hnd.pack()
return self.hnd

class WxWindow(AbstractWindow):
def createWindow(self, parent, title):
self.hnd = wx.Frame(None, -1 , "Hola")
self.hnd.Show(True)
return self.hnd

class AbstractButton(object):
def __init__(self):
self.button = None
self.title = None
def createButton(self):
pass

class TkinterButton(AbstractButton):
def createButton(self,parent, title):
self.button = Tkinter.Button(text=title).pack(side=Tkinter.BOTTOM)

class WxButton(AbstractButton):
def createButton(self,parent, title):
self.button = wx.Button(parent, -1, title)


w = AbstractFactory()
f = w.getFactory('Wx')
a = f.createApp()
b = f.createWindow(a,"Hola")
f.createButton(b, "Hola")
f.run()

jueves, 18 de septiembre de 2008

PATRONES CREACIONALES (I). Patrón Singleton

Este patrón se utiliza para garantizar una única instancia de una clase determinada. Este mecanismo puede ser interesante para ciertos tipos de controles, por ejemplo el acceso a un
determinado recurso compartido.


# singleton:
class Singleton (object):
instance = None
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = object.__new__(cls, *args, **kwargs)
return cls.instance

a = Singleton()
b = Singleton()

print id(a), id(b)


La funcion id() devuelve un entero único y constante durante la vida del objeto si los valores para la función id son idénticos en ambos casos garantizan que clase Singleton ha sido implementada de forma correcta.

A continuación, os dejo un vídeo dividido en tres partes que he encontrado sobre el patrón Singleton


Parte 1


Parte 2


Parte 3

Patrones de diseño

Podemos definir los patrones de diseño como soluciones estándar a problemas de diseño recurrentes. Es decir, son una especie de "recetas" que aplicaremos cuando nos encontremos ante una determinada situación.

En el ámbito software, los patrones de diseño fueron popularizados por el libro "Design Patterns"
escrito por Erich Gamma, Richard Helm, Ralph Johnson y John Vlisides en 1995. Estos cuatro autores son
conocidos como "Gang of Four" (GoF).

Este libro divide los patrones de diseño en tres categorías diferentes:
  • Patrones de Creación
  • Patrones Estructurales
  • Patrones de Comportamiento
Los patrones de diseño nos permiten introducir soluciones software probadas en vez de reinventar la rueda cada vez. De este modo, además de fomentar la robustez del software se incrementa la productividad al disminuirse el tiempo de desarrollo.

En futuros posts trataré en más profundidad los patrones de diseño que me parecen más interesantes y mostraré un implementación de ejemplo en Python para cada uno de ellos.

lunes, 15 de septiembre de 2008

Prólogo

Hace ya un tiempo que tenía ganas de comenzar a escribir un blog. Por fin me he decidido a comenzar con esta nueva aventura. Mi intención es crear un blog sobre lo que más conozco (o por lo menos eso es lo que creo yo) la informática y en concreto la programación informática.

Dentro de la programación informática escribiré sobre todo entradas sobre Python aunque no exclusivamente. Un lenguaje que conocí en mi época de estudiante a través de un libro olvidado en la biblioteca pero que en los últimos tiempos me ha atraído mucho sobre todo para trastear un poco en mi tiempo ocioso. Me parece que es un lenguaje muy elegante con una curva de aprendizaje bastante suave, que contiene una enorme cantidad de librerías fácilmente descargables e instalables y una orientado a una gran productividad.

Por hoy nos quedamos aquí, otro día continuaremos ...