次のような戦略設計パターンを使用して、各動作への継承を回避します。
この方法では、複数の TPlant バージョンは必要なく、複数の動作バージョンのみが必要です。
program Strategy;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TPhotosystesisBehavior = class
public
procedure DoPhotosyntesis; virtual; abstract;
end;
TGreenPhotosyntesisBehavior = class(TPhotosystesisBehavior)
public
procedure DoPhotosyntesis; override;
end;
TOtherPhotosynthesisBehavior = class(TPhotosystesisBehavior)
public
procedure DoPhotosyntesis; override;
end;
TPlant = class
private
function GetPhotoBehavior: TPhotosystesisBehavior;
procedure SetPhotoBehavior(const Value: TPhotosystesisBehavior);
protected
FPhotoBehavior: TPhotosystesisBehavior;
public
procedure PerformPhotosyntesis;
property PhotoBehavior: TPhotosystesisBehavior read GetPhotoBehavior write SetPhotoBehavior;
end;
{ TGreenPhotosyntesisBehavior }
procedure TGreenPhotosyntesisBehavior.DoPhotosyntesis;
begin
Writeln(' - Eating some solar energy, delicious!!');
end;
{ TPlant }
function TPlant.GetPhotoBehavior: TPhotosystesisBehavior;
begin
Result:= FPhotoBehavior;
end;
procedure TPlant.PerformPhotosyntesis;
begin
Writeln('Performing Photosynthesis: ');
if Assigned(FPhotoBehavior) then
FPhotoBehavior.DoPhotosyntesis;
Writeln('Performing Photosynthesis: End');
end;
procedure TPlant.SetPhotoBehavior(const Value: TPhotosystesisBehavior);
begin
FPhotoBehavior := Value;
end;
{ TOtherPhotosynthesisBehavior }
procedure TOtherPhotosynthesisBehavior.DoPhotosyntesis;
begin
Writeln(' - I Do not like Solar Enery! ');
end;
procedure TestGreenPlant;
var Plant: TPlant;
GreenPlantBehavior: TGreenPhotosyntesisBehavior;
begin
Writeln('TestGreenPlant: ');
Writeln('');
Plant := TPlant.Create;
Plant.PerformPhotosyntesis;
Writeln('');
GreenPlantBehavior:= TGreenPhotosyntesisBehavior.Create;
Plant.PhotoBehavior := GreenPlantBehavior;
Plant.PerformPhotosyntesis;
Writeln('');
Writeln('TestGreenPlant: End');
Writeln('');
end;
procedure TestOtherPlant;
var Plant: TPlant;
OtherPlantBehavior: TOtherPhotosynthesisBehavior;
begin
Writeln('TestOtherPlant: ');
Writeln('');
Plant := TPlant.Create;
Plant.PerformPhotosyntesis;
Writeln('');
OtherPlantBehavior:= TOtherPhotosynthesisBehavior.Create;
Plant.PhotoBehavior := OtherPlantBehavior;
Plant.PerformPhotosyntesis;
Writeln('');
Writeln('TestOtherPlant: End ');
Writeln('');
end;
begin
TestGreenPlant;
Writeln('--------------');
TestOtherPlant;
Readln;
end.
アップデート:
必要に応じて、このパターンを Factory と組み合わせて、各タイプで使用する動作を決定することもできます。以下のコードには、TPlant のインスタンスを取得するためのオーバーロードされた関数が 3 つあります。これらすべてが必要なわけではありません。ここでは、デモンストレーションのみを目的としています。
program Strategy;
{$APPTYPE CONSOLE}
uses
SysUtils, TypInfo;
type
TPhotosystesisBehavior = class
public
procedure DoPhotosyntesis; virtual; abstract;
function ToString: String; virtual;
end;
TGreenPhotosyntesisBehavior = class(TPhotosystesisBehavior)
public
procedure DoPhotosyntesis; override;
function ToString: String; override;
end;
TOtherPhotosynthesisBehavior = class(TPhotosystesisBehavior)
public
procedure DoPhotosyntesis; override;
function ToString: String; override;
end;
TBehaviorType = class of TPhotosystesisBehavior;
TEnumBehavior = (GreenPlant, OtherPlant, Unknown);
TPlant = class
private
function GetPhotoBehavior: TPhotosystesisBehavior;
procedure SetPhotoBehavior(const Value: TPhotosystesisBehavior);
protected
FPhotoBehavior: TPhotosystesisBehavior;
public
procedure PerformPhotosyntesis;
property PhotoBehavior: TPhotosystesisBehavior read GetPhotoBehavior write SetPhotoBehavior;
end;
TPlantFactory = class
private
class function InternalGetPlantTyppedInstance(ABehavior: TPhotosystesisBehavior): TPlant;
public
class function GetPlantTyppedInstance(AType: String): TPlant; overload;
class function GetPlantTyppedInstance(AType: TBehaviorType): TPlant; overload;
class function GetPlantTyppedInstance(AType: TEnumBehavior): TPlant; overload;
end;
{ TGreenPhotosyntesisBehavior }
procedure TGreenPhotosyntesisBehavior.DoPhotosyntesis;
begin
Writeln(' - Eating some solar energy, delicious!!');
end;
function TGreenPhotosyntesisBehavior.ToString: String;
begin
Result:= 'TGreenPhotosyntesisBehavior';
end;
{ TPlant }
function TPlant.GetPhotoBehavior: TPhotosystesisBehavior;
begin
Result:= FPhotoBehavior;
end;
procedure TPlant.PerformPhotosyntesis;
begin
Writeln('Performing Photosynthesis: ');
if Assigned(FPhotoBehavior) then
FPhotoBehavior.DoPhotosyntesis;
Writeln('Performing Photosynthesis: End');
end;
procedure TPlant.SetPhotoBehavior(const Value: TPhotosystesisBehavior);
begin
FPhotoBehavior := Value;
end;
{ TOtherPhotosynthesisBehavior }
procedure TOtherPhotosynthesisBehavior.DoPhotosyntesis;
begin
Writeln(' - I Do not like Solar Enery! ');
end;
procedure TestGreenPlant;
var Plant: TPlant;
GreenPlantBehavior: TGreenPhotosyntesisBehavior;
begin
Writeln('TestGreenPlant: ');
Writeln('');
Plant := TPlant.Create;
Plant.PerformPhotosyntesis;
Writeln('');
GreenPlantBehavior:= TGreenPhotosyntesisBehavior.Create;
Plant.PhotoBehavior := GreenPlantBehavior;
Plant.PerformPhotosyntesis;
Writeln('');
Writeln('TestGreenPlant: End');
Writeln('');
end;
procedure TestOtherPlant;
var Plant: TPlant;
OtherPlantBehavior: TOtherPhotosynthesisBehavior;
begin
Writeln('TestOtherPlant: ');
Writeln('');
Plant := TPlant.Create;
Plant.PerformPhotosyntesis;
Writeln('');
OtherPlantBehavior:= TOtherPhotosynthesisBehavior.Create;
Plant.PhotoBehavior := OtherPlantBehavior;
Plant.PerformPhotosyntesis;
Writeln('');
Writeln('TestOtherPlant: End ');
Writeln('');
end;
function TOtherPhotosynthesisBehavior.ToString: String;
begin
Result:= 'TOtherPhotosynthesisBehavior';
end;
{ TPlantFactory }
class function TPlantFactory.GetPlantTyppedInstance(
AType: TBehaviorType): TPlant;
var Behavior : TPhotosystesisBehavior;
begin
Writeln('GetPlantTyppedInstance (TBehaviorType): ');
Writeln('');
Behavior := AType.Create;
Result := InternalGetPlantTyppedInstance(Behavior);
Writeln('');
Writeln(' - GetPlantTyppedInstance (TBehaviorType): Type Created ');
Writeln('');
Writeln('GetPlantTyppedInstance (TBehaviorType): End');
Writeln('');
end;
class function TPlantFactory.GetPlantTyppedInstance(
AType: String): TPlant;
begin
Writeln('GetPlantTyppedInstance (String): ');
Writeln('');
if AType = 'GreenPlant' then
Result := GetPlantTyppedInstance(TGreenPhotosyntesisBehavior)
else if AType = 'OtherPlant' then
Result := GetPlantTyppedInstance(TOtherPhotosynthesisBehavior)
else
raise Exception.Create('Unkown Type');
Writeln('');
Writeln('GetPlantTyppedInstance (String): End');
Writeln('');
end;
class function TPlantFactory.InternalGetPlantTyppedInstance(
ABehavior: TPhotosystesisBehavior): TPlant;
begin
Writeln('GetPlantTyppedInstance (TPhotosystesisBehavior): ');
Writeln('');
Result := TPlant.Create;
Result.PhotoBehavior := ABehavior;
Writeln('');
Writeln('GetPlantTyppedInstance (TPhotosystesisBehavior): Plant Created, Type: '+ABehavior.ToString);
Writeln('');
Writeln('GetPlantTyppedInstance (TPhotosystesisBehavior): End');
Writeln('');
end;
class function TPlantFactory.GetPlantTyppedInstance(AType: TEnumBehavior): TPlant;
begin
Writeln('GetPlantTyppedInstance (TEnumBehavior): ');
Writeln('');
Result := GetPlantTyppedInstance( GetEnumName(TypeInfo(TEnumBehavior) , Ord(AType)) );
Writeln('GetPlantTyppedInstance (TEnumBehavior): End');
Writeln('');
end;
{ TPhotosystesisBehavior }
function TPhotosystesisBehavior.ToString: String;
begin
Result:= 'TPhotosystesisBehavior';
end;
begin
TestGreenPlant;
Writeln('--------------');
TestOtherPlant;
Writeln('--------------');
Writeln('Factory: ');
Writeln('- Green: ');
TPlantFactory.GetPlantTyppedInstance('GreenPlant');
TPlantFactory.GetPlantTyppedInstance(GreenPlant);
TPlantFactory.GetPlantTyppedInstance(TGreenPhotosyntesisBehavior);
Writeln('');
Writeln('- Other: ');
TPlantFactory.GetPlantTyppedInstance('OtherPlant');
TPlantFactory.GetPlantTyppedInstance(OtherPlant);
TPlantFactory.GetPlantTyppedInstance(TOtherPhotosynthesisBehavior);
Readln;
end.
重要: 低レベルの継承がある場合、または非常に単純なプロジェクトでは、これらすべてがボイラープレートになります。ショットの価値があるかどうかを判断する必要があります