Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

 
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-03-2008
harpo harpo is offline
Miembro
 
Registrado: jul 2006
Posts: 35
Poder: 0
harpo Va por buen camino
Thumbs up Patrón

Buenas gente,

a ver si me podeis echar una manita con el rediseño de un programa.

Tengo un form principal, una serie de frames y una máquina de estados para controlar la visualización de los frames, entre otras cosas. Hasta ahora el diseño era un poco chapuza, el form principal contiene las referencias a todos los frames y la creación de los estados de la máquina. A parte, cada frame contiene referencias a otros frames "hermanos" que necesita y referencias al frame principal, con lo cual tengo un lío tremendo de referencias circulares.

Algunas partes del código

Form principal
Código:
TfrMain = class(TForm)
    frToolbar: TfrToolbar;
    procedure mmExitClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    frNavBarLeft    :TfrNavBarLeft;
    frNavBarRight   :TfrNavBarRight;
    frEditPatient   :TfrEditPatient;
    frViewPatient   :TfrViewPatient;
    frBlank         :TfrBlank;
    frViewImage     :TfrViewImage;
    frViewStudy     :TfrVIewStudy;
    frViewImageTwin :TfrViewImageTwin;
    frCamera        :TfrCamera;
    frEditStudy     :TfrEditStudy;
    frPrint         :TfrPrint;
    frProcesses     :TfrProcesses;
  end;


var
  frMain: TfrMain;

implementation

{$R *.dfm}

procedure TfrMain.mmExitClick(Sender: TObject);
begin
  frMain.Close;
end;

procedure TfrMain.FormCreate(Sender: TObject);
begin


  frBlank         :=TfrBlank.Create(Self);
  frNavBarLeft    :=TfrNavBarLeft.Create(Self);
  frViewPatient   :=TfrViewPatient.Create(self);
  frEditPatient   :=TfrEditPatient.Create(Self);
  frViewImage     :=TfrViewImage.Create(Self);
  frViewStudy     :=TfrViewStudy.Create(Self);
  frViewImageTwin :=TfrViewImageTwin.Create(Self);
  frCamera        :=TfrCamera.Create(Self);
  frEditStudy     :=TfrEditStudy.Create(Self);
  frPrint         :=TfrPrint.Create(Self);
  frProcesses     :=TfrProcesses.Create(Self);

  frBlank.Parent          :=Self;
  frNavBarLeft.Parent     :=Self;
  frViewPatient.Parent    :=Self;
  frEditPatient.Parent    :=Self;
  frViewImage.Parent      :=Self;
  frViewStudy.Parent      :=Self;
  frViewImageTwin.Parent  :=Self;
  frCamera.Parent         :=Self;
  frEditStudy.Parent      :=Self;
  frPrint.Parent          :=Self;
  frProcesses.Parent      :=Self;

  sessiondate:=now;
  states:=TStateMachine.Create;

  frNavBarLeft.ReLoadTreeView;
  frMain.TabStop:=false;

  states.Add (
                stBlank,
                frBlank.frEnter,
                frBlank.frExit,
                frBlank,
                true,
                frToolBar.menu
              );

  states.Add (
                stViewPatient,
                frViewPatient.frEnter,
                frViewPatient.frExit,
                frViewPatient,
                true,
                frToolBar.menu
              );

 // y bla bla bla... demás estados ....

  states.Enter(stBlank);
end;
Máquina Estados (parte de interés)
Código:
  TProc = procedure of object;
  {
    TState:
    state type for the State Machine
  }
  TState = record
    id:integer;  //id state (for ex. stBlank, stViewPatient)
    inProc:TProc;    //initial process
    outProc:TProc;    //fianl process
    frame:TFrame; //frame corresponding for this state
    navBarL:Boolean; //bars must be shown
    menu:TMainMenu; //main menu for this frame (use to be main menu of the
                    //toolbar frame
  end;

  {
    TStateMachine:
    Controls the state of the program and manage the interface active frame
  }
  TStateMachine = class
  private
    states:array of TState;    //posible states           
    procedure stExit(id:integer);
  public
    current:integer; // current state
    last:integer;    //last state (for goback function)
    OnRecordChange:TNotifyEvent;
    stack:TStack;
     procedure Add(id:integer;ip,op:TProc;frame:TFrame;nbl:boolean;menu:TMainMenu);     procedure SetInProc(proc:TProc;state:integer);
    procedure Enter(id:integer);

    constructor Create;
    destructor Destroy; override;

var
  states      :TStateMachine;
  sessionDate :TDateTime;

implementation


procedure TStateMachine.Add(id:integer;ip,op:TProc;frame:TFrame;
                            nbl:boolean;menu:TMainMenu);
var
  l :integer;
begin
  l := Length(states);
  SetLength(states,l+1);
  states[l].id := id;
  states[l].inProc := ip;
  states[l].outProc := op;
  states[l].frame := frame;
  states[l].menu := menu;
  states[l].navBarL := nbl;
end;

procedure TStateMachine.Enter(id: integer);
var
  i,j:integer;
begin
  for i := 0 to length(states)-1 do
    if id = states[i].id then
    begin
      stExit(current);
      current := id;
      frMain.frNavBarLeft.Visible := states[i].navBarL;
      frMain.Menu := states[i].menu;
      with states[i].frame do
      begin
        Align := alClient;
        Visible := True;
      end;
      states[i].inProc;
    end;

end;

procedure TStateMachine.stExit(id:integer);
var
  i :integer;
begin
  for i := 0 to length(states)-1 do
  if id=states[i].id then
  begin
    last := current;
    current := -1;
    states[i].outProc;
    states[i].frame.Align := alNone;
    states[i].frame.Visible := False;
  end;
end;
Pues bien, ahora la idea es hacer un diseño más correcto, algo de este tipo:



Y un pequeño resumen, de cómo considero que son/deberían ser las cosas, pero que no consigo ver claro cómo hacer:
  • Un frame representa un "estado" del programa claramente definido.
  • Las acciones del usuario cambian el estado del programa, por lo tanto debe haber un sistema para cambiar entre los estados correspondientes.
  • Cada frame debe ser independiente y no debe incluir units de otros frames "hermanos".
  • Los frames NO deben referenciar al formulario principal directamente, ni otros miembros del mismo.
  • Para los elementos de la pantalla que si o si deben compartirse entre frames, como los botones, o que deben ser persistentes, como los thumbnails, debe haber un sistema que publique globalmente los diferentes bloques (botonera, thumbnails), para que cada frame pueda obtener y manejar los bloques que necesita y conozca, mientras el resto de los bloques permanece desactivado.
  • Debe haber un sistema para transferir datos entre los distintos frames durante un cambio de estado, ya sean imagenes, claves de la DB, u otros parametros.
  • El uso y la asociacion de los frames a los estados, debe ser lo mas transparente posible ( o sea, no tener que agregar el frame en 50 lugares diferentes)
  • Cada frame o estado deberia tener un procedimiento de entrada y de salida, en el que recibe el estado desde o hacia el cual se transfiere, junto con parametros opcionales. Este procedimiento debe ser privado, y no utilizado afuera del frame en cuestion.
  • Los parametros utilizados para la transferencia de datos deben estar especificados en una estructura estandar, como podria ser una lista de nombres y valores.
Ahora las preguntas...
¿Qué patrones de diseño veis aquí?
¿Singleton para la máquina de estados?
¿Alguna manera de evitar el rollo de las referencias circulares... sin hacer el chapuceo de los uses en la implementación?

(Perdón por el rollo :P )
Responder Con Cita
 



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Patron GoF: Factoría ¿Como y cuando se usa? Delphius OOP 2 26-12-2007 06:37:32
En access hay botón buscador-en form permite buscar patron-existe uno en Delphi igual Ale Alvarez OOP 9 26-09-2007 07:13:44
Patrón observador, attach, notify,update ... adpa OOP 5 22-01-2006 01:07:40
Patrón de los Informáticos. obiwuan Varios 20 10-09-2003 14:44:54


La franja horaria es GMT +2. Ahora son las 22:00:34.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi