AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language MVC + Observer Pattern Konzept / Was haltet Ihr davon
Thema durchsuchen
Ansicht
Themen-Optionen

MVC + Observer Pattern Konzept / Was haltet Ihr davon

Ein Thema von FAM · begonnen am 5. Feb 2015 · letzter Beitrag vom 6. Feb 2015
 
FAM

Registriert seit: 22. Dez 2014
47 Beiträge
 
Delphi XE Enterprise
 
#1

MVC + Observer Pattern Konzept / Was haltet Ihr davon

  Alt 5. Feb 2015, 11:30
Delphi-Version: XE
Hallo Zusammen,

ich habe mir mal zum Thema MVC + Observer-Pattern einen konzeptionellen Entwurf überlegt ...

Grundüberlegung war folgende:

Im View werden unterschiedliche Events ausgelöst, über den Controller werden diese dann ausgewertet und die entsprechende Funktion werden dafür aufgerufen. Die Funktionen werden zuvor am jeweiligen Controller registriert.
Verwendungsmöglichkeit: einfaches EventDispatching (Komponentenunabhängig), z.B. GUI-Update

Unabhänig davon sollen Datenmodelle mit "integrierten Observer Pattern" implenetiert werden können.
Verwendungsmöglichkeit: Bei Datenänderung im Model werden entsprechende EventHandlers ausgelöst.

Ich finde das charmante daran ist die Event-Trennung (Kapselung) - Controller gesteuerte Events (MVC) + auto. Model-gesteuerte Events (ObserverPattern)


Was haltet Ihr davon? - möchte nur der "Betriebsblindheit" mal vorbeugen


VIEW

Delphi-Quellcode:
unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, event.fam.types, model.stockpile, controller, StdCtrls, ExtCtrls;

type

  TForm1 = class(TForm)
    LabelEventHandlerDebug: TLabel;
    RadioGroup1: TRadioGroup;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure SetApplicationBackground;
    procedure Button1Click(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
    procedure EventHandlerViewLabelUpdate;
    procedure EventHandlerModelStockpileUpdate;
    procedure RadioButton2Click(Sender: TObject);

  private
    { Private-Deklarationen }

    controller: TController;

    FAMEvents: TEvents;

    StockpileModel: TStockpileModel; // Stockpile model
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  data: TArray<Double>;
begin

  StockpileModel.SetData(data);

end;

procedure TForm1.FormCreate(Sender: TObject);
begin

  { Create eventtype }
  FAMEvents := TEvents.Create();

  { Create controller instances }
  controller := TController.Create();

  { Register Event-Handler }
  controller.OnUpdateUI := EventHandlerViewLabelUpdate;
  controller.OnApplicationBackground := SetApplicationBackground;

  { Create object instances }
  StockpileModel := TStockpileModel.Create();

  { Register Event-Handler for StockpileModel }
  StockpileModel.registerOn(EventHandlerModelStockpileUpdate);

end;

procedure TForm1.RadioButton1Click(Sender: TObject);
begin
  controller.DispatchEvent(FAMEvents.Name.OnUpdateUI);
end;

procedure TForm1.RadioButton2Click(Sender: TObject);
begin
  controller.DispatchEvent(FAMEvents.Name.OnApplicationBackground);
end;

procedure TForm1.SetApplicationBackground;
begin
  self.Color := clBlue;
end;

procedure TForm1.EventHandlerModelStockpileUpdate;
begin
  ShowMessage('EventHandlerModelStockpileUpdate');
end;

procedure TForm1.EventHandlerViewLabelUpdate;
begin
  LabelEventHandlerDebug.caption := ('TListener has been OnUpdateUI.');
end;

end.
CONTROLLER

Delphi-Quellcode:
unit controller;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, event.fam.types;

type

  { Define a procedural type }
  TFAMEvent = procedure of object;

  TController = class
  private
    FUpdateUI: TFAMEvent;
    FApplicationBackground: TFAMEvent;
  public
    FAMEvents: TEvents;
    Constructor Create;
    procedure dispatchEvent(const FAMEventName: String);
    property OnUpdateUI: TFAMEvent read FUpdateUI write FUpdateUI;
    property OnApplicationBackground: TFAMEvent read FApplicationBackground
      write FApplicationBackground;
  end;

implementation

{ TController }

constructor TController.Create;
begin

  { Create eventtype }
  FAMEvents := TEvents.Create();

end;

procedure TController.dispatchEvent(const FAMEventName: String);
begin

  if ((FAMEventName = FAMEvents.Name.OnUpdateUI) and Assigned(FUpdateUI)) then
    FUpdateUI();

  if ((FAMEventName = FAMEvents.Name.OnApplicationBackground) and
    Assigned(OnApplicationBackground)) then
    OnApplicationBackground();

end;

end.
Model

Delphi-Quellcode:
unit model.stockpile;

interface

uses
  model;

type

  { Stockpile Model }
  TStockpileModel = class(TModel)
  private
    data: TArray<Double>;
  public
    function GetData: TArray<Double>;
    procedure SetData(data: TArray<Double>);
  end;

implementation

{ TStockpileModel }

function TStockpileModel.GetData: TArray<Double>;
begin
  result := self.data;
end;

procedure TStockpileModel.SetData(data: TArray<Double>);
begin
  self.data := data;
  // alle Ereignis-Behandlungs-Routinen der Liste aufrufen
  // wurde mit registerOn an das Model regestriert
  notify;
end;

end.
MODEL (Eltern - Klasse)
Delphi-Quellcode:
unit model;

interface

type
  TEvent = procedure of object;

  TModel = class(tObject)
  protected
    // interne Liste
    OnChange: array of TEvent;
    // Aufruf aller Routinen der Liste
    procedure notify;
  public
    // neuer 'Event-Handler' in Liste
    procedure registerOn(routine: TEvent);
    // 'Event-Handler' aus Liste entfernen
    procedure registerOff(routine: TEvent);
  end;

implementation

// registriert neue routinen an den controller
procedure TModel.registerOn(routine: TEvent);
var
  n: integer;
begin
  n := Length(OnChange);
  SetLength(OnChange, n + 1);
  OnChange[n] := routine;
end;

// de-registriert routinen vom controller
procedure TModel.registerOff(routine: TEvent);
var
  i, j: integer;
begin
  i := Low(OnChange);
  while i <= High(OnChange) do // High liefert -1 bei leerem Array
  begin
    if @OnChange[i] = @routine // mit '@' nur Adressen vergleichen
    then
    begin
      for j := i to High(OnChange) - 1 do
        OnChange[j] := OnChange[j + 1];
      SetLength(OnChange, Length(OnChange) - 1);
    end
    else
      i := i + 1;
  end;
end;

// alle Ereignis-Behandlungs-Routinen der Liste aufrufen
procedure TModel.notify;
var
  i: integer;
begin
  for i := Low(OnChange) to High(OnChange) do
    OnChange[i];
end;

end.

Events-Types


Delphi-Quellcode:
unit event.fam.types;

interface

type

  Events = record
    onUpdateUI: string;
    onApplicationBackground: string;
  end;

  TEvents = class
  private
    FEvents: Events;
  public
    Constructor Create;
    property Name: Events read FEvents;

  end;

implementation

{ EventTypes }

constructor TEvents.Create;

var
  _FEvents: Events;

begin

  _FEvents.onUpdateUI := 'onUpdateUI';
  _FEvents.onUpdateUI := 'onApplicationBackground';

  FEvents := _FEvents;

  Finalize(_FEvents);
  FillChar(_FEvents, SizeOf(_FEvents), 0);

end;

end.

Geändert von FAM ( 5. Feb 2015 um 11:35 Uhr)
  Mit Zitat antworten Zitat
 

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:00 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz