2

割り当てた発射物クラスを無限にインスタンス化できるオブジェクト ファクトリの武器クラスを作成したいと考えています。武器クラスと発射体クラスは「抽象」クラスとして使用されます (Delphi 7 が抽象クラスをサポートしていないことは知っています)。

現在、projectileType を適切にインスタンス化する Weapon.shoot() を実装する方法がわかりません (SimpleWeapon クラスは、SimpleProjectile を projectileType として使用します)。

procedure Weapon.shoot();
var g : Projectile;
begin
        // instanciate ammo type
        g := projectileType.create();
        g.init();
end; 

まず、projectileType.create() は、Projectile 変数に直接割り当てることができない TObject を返します。また、projectileType(g) による TObject のキャストも機能しません。

第二に、g が projectileType にキャストされるようにするにはどうすればよいですか? その特定のクラスの init() メソッドを使用できます。

UML ダイアグラム

4

4 に答える 4

3

クラス タイプを宣言しSimpleProjectileClass = class of SimpleProjectileます。次に、 projectType がそのタイプを返すようにします: projectType: SimpleProjectileClass

于 2013-05-26T14:42:43.067 に答える
2

武器は、発射できる発射体の種類を知る必要はありません。発砲/射撃することだけを知っている必要があります。

したがって、武器戦略を実装することが最善のアドバイスです

type
  TWeapon = class;

  IWeaponStrategy = interface
    ['{B47CD780-906D-4515-BDA6-1EC8118BC29E}']
    procedure Shoot( AWeapon : TWeapon );
  end;

  TWeapon = class
  private
    FStrategy : IWeaponStrategy;
  public
    procedure Shoot;

    procedure SetStrategy( AStrategy : IWeaponStrategy );
  end;

implementation

{ TWeapon }

procedure TWeapon.SetStrategy( AStrategy : IWeaponStrategy );
begin
  FStrategy := AStrategy;
end;

procedure TWeapon.Shoot;
begin
  FStrategy.Shoot( Self );
end;

弾丸を発射する武器を取得するには、WeaponBulletStrategy をビルドします。

type
  TWeaponBulletStrategy = class( TInterfacedObject, IWeaponStrategy )
  protected
    procedure Shoot( AWeapon : TWeapon );
  end;

implementation

procedure TWeaponBulletStrategy.Shoot( Aweapon : TWeapon );
begin
  // Build the Bullet Instance and initialize
end;

武器の発射動作を簡単に変更したり、武器のクラスを変更せずに新しい発射体クラスを実装したりできるようになりました。

于 2013-05-26T15:34:13.840 に答える
0

ここに問題に対する私の見解の洞察があります:

type
  TProjectile = class
  protected
    function GetDamage: Integer; virtual; abstract;
    function GetPenetration: Double; virtual; abstract;
  public
    procedure DoExtenalBallistics(WindSpeed, WindDirection: Real); virtual;
    procedure DoInternalBallistics(Acceleration: Real); virtual;
    procedure DoTerminalBallistics(TargetArmor: Real); virtual;
    property Damage: Integer read GetDamage;
    /// <summary>
    /// Sorry, can not resist ;-)
    /// </summary>
    property Penetration: Double read GetPenetration;
  end;

procedure TProjectile.DoExtenalBallistics(WindSpeed, WindDirection: Real);
begin
  // TODO : do parabolic travel within the gravity pull of Earth, affected by wind
end;

procedure TProjectile.DoInternalBallistics(Acceleration: Real);
begin
  // TODO : do gain kinetic energy in the acceleration chamber
end;

procedure TProjectile.DoTerminalBallistics(TargetArmor: Real);
begin
  // TODO : TargetHitPoitns - (Damage / (TargetArmor - Penetration)) or something
end;

type
  TProjectileType = class of TProjectile;

  TFirearm = class
  protected
    function GetSupportedProjectile: TProjectileType; virtual; abstract;
  public
    function CanShoot(Projectile: TProjectile): Boolean; virtual;
    procedure Shoot;
    property SupportedProjectile: TProjectileType read GetSupportedProjectile;
  end;

function TFirearm.CanShoot(Projectile: TProjectile): Boolean;
begin
  Result := Projectile is SupportedProjectile;
end;

procedure TFirearm.Shoot;
var
  Projectile: TProjectile;
begin
  Projectile := SupportedProjectile.Create;
  Projectile.DoInternalBallistics(CardridgePowder);
  Projectile.DoExtenalBallistics(Theatre.Wind.Speed, Theatre.Wind.Direction);
  Projectile.DoTerminalBallistics(Targer.Armors);
  { ... }
  { ofc is CanShoot returns false, then http://i192.photobucket.com/albums/z96/M4builder/destructivetestedbarrrels01copy.jpg and Firearm.Owner.Fingers - 5 }
end;

type
  TSmoothBoreProjectile = class(TProjectile)
  end;

  TBuckshot = class(TSmoothBoreProjectile)
  end;

  Flechette = class(TSmoothBoreProjectile)
  end;

  TShotgun = class(TFirearm)
  protected
    function GetSupportedProjectile: TProjectileType; override;
  end;

function TShotgun.GetSupportedProjectile: TProjectileType;
begin
  Result := TSmoothBoreProjectile;
end;

簡潔にするために、いくつかの必要なオーバーライドを省略し (モデルは元のクラス図よりもはるかに大きい)、提案されたInitメソッドを、実際の発射体が行うべきことに関連する疑似に置き換えました。

于 2013-05-26T19:04:23.027 に答える