分享
 
 
 

Delphi Implementation MVC

王朝delphi·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

OSZ Handel I

Informatik

Objektorientierte Programmierung (OOP)

M-V-C Implementierung

S. Spolwig

[Home | Gymn. Oberstufe | Informatik | Unterrichtsmaterialien | Delphi ]

Hinweise zur Implementation von MVC mit DELPHI

Die allgemeine Beschreibung finden Sie unter MVC-Konzept. Den kompletten Quellcode unter den Links im Text, weitere Programmbeispiele unter Modellierung mit UML und downloads.

Alle Rahmenplanentwickler, die etwas auf sich halten, haben in den letzten Jahren die Behandlung des MVC-Konzepts in die Unterrichtspläne geschrieben. Was auch immer unter Behandlung verstanden wird, für unsere Schule hieß das schon immer, alle Programme (also auch die sogenannten kleinen) werden unter diesem Design entwickelt und geschrieben. Das bedeutet, daß die Implementierung der Einfachheit des Konzepts (Trenne Daten und ihre Repräsentation!) zu folgen hat und der Programmieraufwand niedrig gehalten werden muß.

Genauso einfach ist scheinbar die Programmieraufgabe: benötigt werden Mechanismen, die die Daten zwischen GUI und Model hin- und hertransportieren, wenn entsprechende Ereignisse aufgetreten sind. Dazu kommen in Frage:

Polling

D. h. das GUI fragt das Model nach den Daten ab und aktualisiert den View.

Observer Pattern Design

ist ein Mechanismus, der automatisch jede Änderung des Zustands des Datenobjekts überwacht und erforderliche Aktualisierungen vornimmt. Näheres in der Fachliteratur. JAVA bietet dazu passende Klassen an, um Controller/View-Ereignisse 'zu Fuß' zu programmieren. In DELPHI ist das eher unüblich.

Selbstgeschriebene Ereignisroutinen

Das Model erhält eine Ereignismethode (Zeiger), die vom GUI ausgewertet wird und automatisch den View aktualisiert.

Bewertung

Die Aufgabe / Beispiel

Ein Programm berechnet den B.M.I.-Faktor einer Person. Es hat eine Fachklasse TPerson und die GUI-Klasse TFensterFrm.

Der Button

updateModel schickt die Daten ans Model

updateView holt die Daten und aktualisiert den View

Abnehmen reduziert den Wert von Gewicht.

Bild 1

1.1 Manuelles Polling über GUI-Komponenten

Die Aktionen werden durch getrennte GUI-Komponenten realisiert, was bei den meisten Anwenderprogrammen angebracht ist.

Die Fachklasse TPerson hat nur die notwendigen Set- und Get-Methoden.

TPerson = class(TObject)

private

Name : string;

Groesse : real;

Gewicht : real;

public

...

procedure SetName (n : string);

function GetName : string;

...

Die GUI-Klasse übernimmt Control- und Viewaufgaben.

unit uFenster;

INTERFACE

// ======================================================================

uses

...

uPerson;

TFensterFrm = class(TForm)

GroesseLbl: TLabel;

...

procedure updModelBtnClick (Sender: TObject);

procedure updViewBtnClick(Sender: TObject);

procedure AbnehmBtnClick(Sender: TObject);

private

Person : TPerson; // --- Model PERSON

procedure Init;

procedure DatenAktualisieren; // -- hier der Datentransport

procedure MaskeAktualisieren;

end;

IMPLEMENTATION

// ======================================================================

....

Procedure TFensterFrm.DatenAktualisieren;

// ----------------------------------------------------------------------

// Eingaben aus den Editfeldern an das Model-Objekt übergeben

begin

Person.SetName (NameEdt.Text);

Person.SetGroesse (StrToFloat (GroesseEdt.Text));

Person.SetGewicht (StrToFloat (GewichtEdt.Text));

end;

procedure TFensterFrm.updModelBtnClick(Sender: TObject);

// ----------------------------------------------------------------------

// Ereignis starten

begin

DatenAktualisieren;

Init; // Eingaben im Fenster löschen

end;

procedure TFensterFrm.MaskeAktualisieren;

// ----------------------------------------------------------------------

// Objektdaten an die View-Komponenten übergeben

begin

NameEdt.Text := Person.GetName;

GroesseEdt.Text := FloatToStr (Person.GetGroesse);

GewichtEdt.Text := FloatToStr (Person.GetGewicht);

BmiEdt.Text := FloatToStr (Person.HatBMI);

end;

procedure TFensterFrm.updViewBtnClick(Sender: TObject);

// ----------------------------------------------------------------------

// Ereignis starten

begin

MaskeAktualisieren

end;

...

1.2 Manuelles Polling (halbautomatisch) über GUI-Komponenten

Wenn die Ausgabe von Ergebnissen und Daten unmittelbar nach der Eingabe erwünscht ist, kann man den Aufruf MaskeAktualisieren in die upDateModel-Komponente legen und auf die upDateView-Komponente verzichten. Der Rest bleibt gleich.

procedure TFensterFrm.updModelBtnClick(Sender:TObject);

// ----------------------------------------------

// Ereignis starten

begin

DatenAktualisieren;

Init;

MaskeAktualisieren;

end;

Bild 2

2. Observer Pattern Design

[url=http://dev.csdn.net/delphi_6.1.6.htm][url=http://dev.csdn.net/delphi_6.1.8.htm][url=http://dev.csdn.net/delphi_6.1.7.htm][url=http://dev.csdn.net/delphi_6.1.9.htm]

Bild 3 - [Klicken Sie für den Quelltext auf die Klasse]Reichlich Aufwand, um eine Klasse Person zu observieren ...Durch die Auslagerung von Observer-Code in die Oberklasse bleibt dann aber nur der RunObservers-Aufruf in den Set-Methoden. procedure TPerson.SetName (n : string);//----------------------------------------------begin fName := n; fObserverMgr.RunObservers; // Message absendenend;und im GUI procedure TFensterFrm.FormShow(Sender: TObject);// ---------------------------------------------begin Person := TPerson.Create; Person.AddObserver(MaskeAktualisieren,self);end;
Bild 4Dem GUI ist ein zweiter View hinzugefügt, der vom Observer mit bedient wird.
3. Automatische Aktualisierung durch selbstgeschriebene Ereignisroutinen

Die Fachklasse hat außer den üblichen Set.. / Get-Methoden zusätzlich Code zur Ereignisbehandlung. Will man sicherstellen, daß die Änderung eines jeden Attributwertes verarbeitet wird, so braucht jede betreffende Methode die Variable OnChanged, die in der GUI-Klasse referenziert wird und die Aktualisierung anstößt.

Hier wird mit einem selbstdefinierten Typ TNotifyChange gearbeitet. Delphi stellt einen Typ TNotifyEvent zur Verfügung, der mit Properties ähnlich arbeitet.

Bild 5

unit uPerson;

INTERFACE

// ======================================================================

type

TNotifyChange = procedure of object; // Deklaration eines Methodenzeigertyps

TPerson = class(TObject)

private

Name : string;

...

public

OnChanged : TNotifyChange; // Vereinbarung einer

... // Referenzvariablen/Ereignismethode

end;

IMPLEMENTATION

// ======================================================================

...

procedure TPerson.SetGroesse (gr : real);

(* ----------------------------------------- *)

begin

Groesse := gr;

if assigned(OnChanged) // Ereignis auslösen

then OnChanged;

end;

procedure TPerson.Abnehmen;

(* ----------------------------------------- *)

begin

Gewicht := Gewicht - 1;

if assigned(OnChanged) // Ereignis auslösen

then OnChanged;

end;

...

END. // ----- UNIT -------

In der GUI-Klasse sorgt die Methode Person.OnChanged in FormCreate dafür, daß bei jedem Event die GUI-Methode MaskeAktualisieren ausgeführt wird.

Leider kann das in bestimmten Fällen zu Problemen führen. Editfelder, die sich gut für kombinierte Ein- und Ausgabe eignen, dürfen nicht für die Ausgabe von Rechenoperationen angesprochen werden; es sind also andere GUI-Komponenten dafür erforderlich. Die korrekte Initialisierung von Gewicht und Groesse

mit 0 führt zu einer Exception wegen der unerlaubten Division durch Null bei Errechnung des BMI.

Reine Textfelder sind unproblematisch.

unit uFenster;

INTERFACE

// ======================================================================

uses

...

uPerson;

type

TFensterFrm = class(TForm)

GroesseLbl : TLabel;

...

procedure FormCreate (Sender: TObject);

procedure updModelBtnClick (Sender: TObject);

procedure AbnehmBtnClick (Sender: TObject);

procedure EndeBtnClick (Sender: TObject);

private

Person : TPerson; // --- Model PERSON

procedure Init;

procedure DatenAktualisieren; // --- hier der Datentransport

procedure MaskeAktualisieren;

public

end;

var

FensterFrm: TFensterFrm;

IMPLEMENTATION

// ======================================================================

{$R *.DFM}

procedure TFensterFrm.FormCreate(Sender: TObject);

// ----------------------------------------------------------------------

begin

FensterFrm.Init;

Person := TPerson.Create;

Person.OnChanged := MaskeAktualisieren; // Methodenzeiger mit Methode

end; // verknüpfen

...

procedure TFensterFrm.DatenAktualisieren;

// ----------------------------------------------------------------------

// wie vorher

...

procedure TFensterFrm.updModelBtnClick(Sender: TObject);

// ----------------------------------------------------------------------

begin

DatenAktualisieren;

end;

procedure TFensterFrm.MaskeAktualisieren;

// ----------------------------------------------------------------------

begin

NameEdt.Text := Person.GetName;

BmiEdt.Text := FloatToStr(Person.HatBMI);

end;

procedure TFensterFrm.AbnehmBtnClick(Sender: TObject);

// ----------------------------------------------------------------------

begin

Person.Abnehmen;

end;

end. // ------ UNIT -------

Bewertung

1. Polling

Manuelles Polling (1.1. und 1.2) haben sich seit 10 Jahren im Unterricht bewährt und sind unaufwendig. An unserer Schule werden alle Programme, beginnend im Anfangsunterricht mit einer Fachklasse bis zu großen Projekten, in dieser Weise von den Schülern bearbeitet. Die Datenklassen sind frei von jeder technischen Erweiterung. Das erlaubt eine sehr einfache und klare OOA und Implementierung.

2. Observer Pattern Design

Viel Technik, wenig Erkenntnisgewinn (s.o.). Der Programmieraufwand pro observiertem Objekt ist so umfangreich, daß er sich für den Unterricht verbietet, wenn Schüler den kompletten Observer-Code schreiben sollten, zumal das durchaus nicht trivial ist. Eine Möglichkeit wäre, das ganze Paket als Bibliothek abzulegen.

Bei dieser als auch der dritten Variante bleiben Fachklassen nicht von proprietärem Code frei, der sie mit dem Betriebssystem verknüpft, was einer Portierung im Wege steht. Der schöne Anspruch, das in Fachklassen auch nur Anwendungsdaten und Anwendungslogik enthalten sein sollen, ist dahin.

3. Selbstgeschriebene Ereignisroutinen

Die selbstgeschriebene Ereignissteuerung ist eher eine Bastlerlösung. TNotifyChange ist ein Prozedurtyp, ein ebenso mächtiges wie undurchsichtiges Konstrukt. Onchange eine Prozedurvariable, also gleichermaßen Attribut und Prozedur und damit proprietär belastet. Die o. g. Restriktionen und Fehler lassen Zweifel an einen routinemäßigen Einsatz im Unterricht aufkommen.

-------------------

Literatur u. Links

Hilfehandbuch Delphi 7

Amrhein, B.: Designpattern für Graphische Benutzeroberflächen

http://www.hta-be.bfh.ch/~amrhein/Skripten/Swing/Pattern.pdf

Höstklint, C.: Simple Observer Pattern

http://www.delphi3000.com/member.asp?ID=9713

Paulus, H.: Das MVC-Konzept. (Schöne Präsentation)

http://informatikag.bildung-rp.de/assets/download/D1-Paulus-Farben.pps

© 15. Oktober 2004 Siegfried Spolwig

[url=http://dev.csdn.net/#top]

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有