Thema: Delphi Ampelkreuzung

Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Ampelkreuzung

  Alt 9. Dez 2012, 13:28
Da in der Software Entwicklung derzeit "Design-Patterns" sehr beliebt sind, könntest du für Fortbildungzwecke das "State-Pattern" anschauen.

Eine Ampel ist eine State-Maschine. Verschiedene Ampelphasen können nur in bestimmten Phasen enden.

Durch Patterns soll der Quelltext u.a. übersichtlicher werden.

http://de.wikipedia.org/wiki/Zustand...wurfsmuster%29
http://www.philipphauer.de/study/se/...tern/state.php
Übersichtlicher ist hierbei nicht zu verwechseln mit weniger Code. Im Gegenteil es gibt mehr Code.
Der Vorteil ist aber, dass man die Gesamtproblematik zerlegt in kleine übersichtliche Häppchen (die einzelnen States).

Und je komplizierter der Sachverhalt umso mehr Vorteile bringt es.

Zum Vergleich mal FizzBuzz (Fun Code of the Week # 5 - Nick Hodges) in der simpelsten Version:
Delphi-Quellcode:
program FizzBuzz;

uses
  SysUtils, StrUtils;

var
  s: string;
  i: Integer;

begin

  for i := 1 to 100 do
    begin
      s := ifThen( i mod 3 = 0, 'Fizz', '' );
      s := IfThen( i mod 5 = 0, s + 'Buzz', s );
      WriteLn( IfThen( s = '', IntToStr( i ), s ) )
    end;

  ReadLn;
 
end.
und einmal mit dem StatePattern
Delphi-Quellcode:
program FizzBuzz_StatePattern;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  FizzBuzz in 'FizzBuzz.pas',
  FizzBuzzStates in 'FizzBuzzStates.pas';

var
  FizzBuzz : TFizzBuzz;

begin

  FizzBuzz := TFizzBuzz.Create;
  try

    FizzBuzz.Execute( 1, 100 );

  finally
    FizzBuzz.Free;
  end;

  Readln;

end.
Delphi-Quellcode:
unit FizzBuzz;

interface

type
  TCustomFizzBuzzState = class;
  TFizzBuzzStateClass = class of TCustomFizzBuzzState;

  TFizzBuzz = class
    private
      FIndex : Integer;
      FState : TCustomFizzBuzzState;
    protected
      procedure DoWriteIndex;
      procedure DoWriteString( const AString : string );
      procedure DoWriteEOL;
      procedure DoIncIndex;
      procedure DoSetState( AStateClass : TFizzBuzzStateClass );
    public
      procedure Execute( AIndex, ACount : Integer );
  end;

  TCustomFizzBuzzState = class
    private
      FContext : TFizzBuzz;
    protected
      procedure DoWriteIndex;
      procedure DoWriteString( const AString : string );
      procedure DoWriteEOL;
      procedure DoIncIndex;
      procedure DoSetState( AStateClass : TFizzBuzzStateClass );
    public
      constructor Create( AContext : TFizzBuzz );
      procedure Consume( AValue : Integer ); virtual; abstract;
  end;

implementation

uses
  FizzBuzzStates;

  { TFizzBuzzStateBase }

constructor TCustomFizzBuzzState.Create( AContext : TFizzBuzz );
begin
  inherited Create;
  FContext := AContext;
end;

procedure TCustomFizzBuzzState.DoIncIndex;
begin
  FContext.DoIncIndex;
end;

procedure TCustomFizzBuzzState.DoSetState( AStateClass : TFizzBuzzStateClass );
begin
  FContext.DoSetState( AStateClass );
end;

procedure TCustomFizzBuzzState.DoWriteEOL;
begin
  FContext.DoWriteEOL;
end;

procedure TCustomFizzBuzzState.DoWriteIndex;
begin
  FContext.DoWriteIndex;
end;

procedure TCustomFizzBuzzState.DoWriteString( const AString : string );
begin
  FContext.DoWriteString( AString );
end;

{ TFizzBuzz }

procedure TFizzBuzz.Execute( AIndex, ACount : Integer );
begin
  DoSetState( TFizzState );
  FIndex := AIndex;
  while FIndex < AIndex + ACount do
    begin
      FState.Consume( FIndex );
    end;
end;

procedure TFizzBuzz.DoIncIndex;
begin
  Inc( FIndex );
end;

procedure TFizzBuzz.DoSetState( AStateClass : TFizzBuzzStateClass );
begin
  if Assigned( FState )
  then
    FState.Free;

  FState := AStateClass.Create( Self );
end;

procedure TFizzBuzz.DoWriteEOL;
begin
  Writeln;
end;

procedure TFizzBuzz.DoWriteIndex;
begin
  write( FIndex );
end;

procedure TFizzBuzz.DoWriteString( const AString : string );
begin
  write( AString );
end;

end.
Delphi-Quellcode:
unit FizzBuzzStates;

interface

uses
  FizzBuzz;

type
  TStartState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TFizzState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TBuzzState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TFizzBuzzState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TNumberState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TEndLineState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

implementation

{ TStartState }

procedure TStartState.Consume( AValue : Integer );
begin
  DoSetState( TFizzState );
end;

{ TFizzState }

procedure TFizzState.Consume( AValue : Integer );
begin
  if AValue mod 3 = 0
  then
    begin
      DoWriteString( 'Fizz' );
      DoSetState( TFizzBuzzState );
    end
  else
    DoSetState( TBuzzState );
end;

{ TEndLineState }

procedure TEndLineState.Consume( AValue : Integer );
begin
  DoWriteEOL;
  DoIncIndex;
  DoSetState( TStartState );
end;

{ TBuzzState }

procedure TBuzzState.Consume( AValue : Integer );
begin
  if AValue mod 5 = 0
  then
    begin
      DoWriteString( 'Buzz' );
      DoSetState( TEndLineState );
    end
  else
    DoSetState( TNumberState );
end;

{ TNumberState }

procedure TNumberState.Consume( AValue : Integer );
begin
  DoWriteIndex;
  DoSetState( TEndLineState );
end;

{ TFizzBuzzState }

procedure TFizzBuzzState.Consume( AValue : Integer );
begin
  if AValue mod 5 = 0
  then
    begin
      DoWriteString( 'Buzz' );
    end;
  DoSetState( TEndLineState );
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat