Tema: una ayudita
Ver Mensaje Individual
  #2  
Antiguo 15-01-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Reputación: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
¿Y cómo imaginas que tal unidad o dll (en caso de que exista) va a manejar las distintas versiones? De una u otra forma tendrá que tener código para cada una; así que tu pregunta más bien sería:

¿Existe una unidad o dll que maneje listas de Winamp para no tener yo que programarla?

Es una pregunta válida.

Pero si quieres programarla tú mismo tendrás que manejar la distintas versiones de una u otra forma.

Esto no lo puedes evitar. Pero sí puedes diseñarla de manera que no tengas que alterar el código que ´haga uso de tal unidad.

Para empezar fíjate que la lista como tal la puedes mantener en memoria sin depender del formato en particular. Digamos que cada entrada de la lista la guardas en una clase:

Código Delphi [-]
type
  TWinampItem = class
  public
    property Duration: Double;
    property Artist: String;
    property Theme: String;
  end;

Puedes entonces usar un TObjectList (unidad Contnrs) para almacenar objetos de esta clase.

Entonces lo único que debe preocuparte es cómo leer una lista desde un archivo y como guardarla en un archivo:

Código Delphi [-]
type
  TWinampList = class(TObjectList)
  public
    procedure LoadFromFile(FileName: String); virtual;
    procedure SaveToFile(FileName: String); virtual;
  end;

El declarar los métodos como virtuales te permite diseñar un descendiente de esta clase por cada nueva versión:

Código Delphi [-]
type
  TWinampList27 = class(TWinampList)
    procedure LoadFromFile(FileName: String); override;
    procedure SaveToFile(FileName: String); override;
  end;

  TWinampList31 = class(TWinampList)
    procedure LoadFromFile(FileName: String); override;
    procedure SaveToFile(FileName: String); override;
  end;

  TWinampList56 = class(TWinampList)
    procedure LoadFromFile(FileName: String); override;
    procedure SaveToFile(FileName: String); override;
  end;

Cada descendiente se ocupa del formato en particular para implementar los métodos virtuales. Tu aplicación (o aplicaciones) que requieran usar listas de Winamp lo único que requieren es que se les provea de un objeto TWinampList sin tener que saber exactamente de qué descendiente en particular se trata.

Veamos un ejemplo. Suponte que tu aplicación tiene un botón para cargar una lista de ejecución. Con este botón el usuario escoge un archivo del disco y tu aplicación carga la lista en un ListBox:

Código Delphi [-]
procedure LoadButtonClick(Sender: TObject);
var
  I: Integer;

begin
  if OpenDialog.Execute then
  begin
    WinampList.LoadFromFile(OpenDialog.FileName);

    for I := 0 to WinampList.Count - 1 do
        ListBox.Items.Add(TWinampItem(WinampList[i]).Theme);
  end;
end;

donde WinampList es un objeto de tipo TWinampList (la clase base).

Lo importante aquí es que idependientemente de qué descendiente de TWinampList uses para construir el obejto WinampList, el código de tu botón no cambia, asó como no cambiará cualquier código que deba utilizar WinampList.

Lo que hay que ver entonces es cómo escoges cual descendiente usar:

Código Delphi [-]
WinampList := TWinampList27.Create;
WinampList := TWinampList31.Create;
WinampList := TWinampList56.Create;

sin tener que alterar el código que ya tienes. Lo más simple sería cambiar por la línea adecuada con cada nueva versión y recompilar pero a fin de cuentas no esperarás que todos los usuarios trabajen con la misma versión: quizá quieran leer una lista de un formato distinto al que tienes preparado.

Una opción elegante es usar un fábrica. En la unidad donde declares la clase base, pones una variable global que mantenga una asociación entre la versión y la clase a usar:

Código Delphi [-]
unit WinampList;

interface

uses
  Classes, Contnrs;

type
  TWinampList = class(TObjectList)
  public
    procedure LoadFromFile(FileName: String); virtual; abstract;
    procedure SaveToFile(FileName: String); virtual; abstract;
  end;

  TWinampListClass = class of TWinampList;

var
  Factory: TStringList;

implementation

initialization
  Factory := TStringList.Create;
end.

Factory mantendría la asociación:

'ver27' --> TWinampList27
'ver31' --> TWinampList31
'ver56' --> TWinampList56

etc.

Cada nueva versión la implementas en una unidad distinta y ahí añades la correspondiente asociación:

Código Delphi [-]
unit WinampList27;

interface

uses
  WinampList;

type
  TWinampList27 = class(TWinampList)
    procedure LoadFromFile(FileName: String); override;
    procedure SaveToFile(FileName: String); override;
  end;

implementation

initialization
  Factory.AddObject('ver27', TObject(TWinampList27));
end.

Con esto, lo único que necesitas para construir WinampList adecuadamente es una cadena con el número de versión:

Código Delphi [-]
var
  Version: String; // contiene el número de versión

...

var
  WinampList: TWinampList;
  WinampListClass: TWinampListClass;

begin
  WinampListClass := TWinampListClass(Factory.Objects[Version]);
  WinampList := WinampListClass.Create;
end;

Al requerir sólo el número de versión para construir la clase adecuada logras no tener que incluir la unidad correspondiente en el código de tu aplicación, únicamente tienes que incluir la unidad de la clase base: WinampList. Así tal código no necesita ni siquiera ser recompilado con cada versión nueva que aparezca.

Incluso puedes permitir que el usuario escriba el mismo de qué versión es la lista que va a leer y todo el formulario donde haga esto no cambia en lo absoluto con la aparición de nuevas versiones.

Tomando en cuenta que el código del botón para leer una lista desde el disco es seguramente tan sólo un ejemplo, en balance, aun cuando debes preocuparte por implementar LoadFromFile y SaveToFile para cada versión, ganas bastante al dejar intacto todo el código alrededor.

// Saludos
Responder Con Cita