本文主要是介绍《GOF设计模式》—抽象工厂(Abstract Factory)—Delphi源码示例:基于抽象工厂的迷宫,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- 实现:
- 如果TMaze.Create是传递一个对象当作参数来建立rooms、walls及doors;如此你可以以不同的参数来改变rooms、walls及doors的类。
- 请注意MazeFactory也就是工厂方法(Factory Method)的一个集合;这是最通常实现抽象工厂模式的方式。同时请注意MazeFactory不是一个抽象类(abstract class)它的行为包括抽象工厂(abstractFactory)及具体工厂(ContreteFactory);这也是另一种以抽象工厂实现简单应用系统的方式。因为MazeFactory是一种具体类包含所有的工厂方法所以容易以继承及覆盖的方式建立新的MazeFactory。
- 代码:
- unit uMazeFactory;
- interface
- uses
- Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls;
- type
- {房间的四个方向}
- TDirection = (North = 0,South = 1,East = 2,West = 3);
- const
- DirectionNames: array[TDirection] of string = ('北', '南', '东', '西');
- type
- {咒语}
- TSpell = class
- private
- FKey: string;
- public
- property Key: string read FKey write FKey;
- end;
- {迷宫构件}
- TMapSite = class
- private
- FStateMsg: string;
- public
- function Enter: Boolean; virtual; abstract;
- //---
- property StateMsg: string read FStateMsg write FStateMsg;
- end;
- {房间}
- TRoom = class(TMapSite)
- private
- FSides: array[TDirection] of TMapSite;
- FRoomNumber: Integer;
- protected
- function GetSides(Direction: TDirection): TMapSite;
- procedure SetSides(Direction: TDirection; const Value: TMapSite);
- public
- constructor Create(ARoomNumber: integer);
- destructor Destroy; override;
- //---
- function Enter: Boolean; override;
- //---
- property RoomNumber: Integer read FRoomNumber;
- property Sides[Direction: TDirection]: TMapSite read GetSides write SetSides;
- end;
- TRoomWithABomb = class(TRoom)
- private
- FBomb: boolean;
- public
- constructor Create(ARoomNumber: integer; Bombed: boolean = false);
- //---
- procedure Initialize1(Bombed: boolean);
- function HasBomb(): Boolean;
- function Enter: Boolean; override;
- end;
- TEnchantedRoom = class(TRoom)
- private
- FSpell: TSpell;
- public
- constructor Create(ARoomNumber: integer; Spell: TSpell = nil);
- destructor Destroy; override;
- //---
- function Enter: Boolean; override;
- //---
- function HasSpell(): boolean;
- function PickUpSpell(): TSpell;
- end;
- {墙壁}
- TWall = class(TMapSite)
- public
- function Enter: Boolean; override;
- end;
- TBombedWall = class(TWall)
- private
- FBomb: boolean;
- public
- constructor Create(Bombed: boolean = false);
- //---
- function Enter: Boolean; override;
- procedure Initialize1(Bombed: boolean);
- end;
- {门}
- TDoor = class(TMapSite)
- private
- FRoom1,FRoom2: TRoom;
- //--门是否开启
- FIsOpen: Boolean;
- procedure Initialize(room1,room2: TRoom);
- public
- constructor Create(room1,room2: TRoom); virtual;
- destructor Destroy; override;
- //---
- function Enter: Boolean; override;
- {从一个房间(传入参数)进入另一个房间(输出结果)}
- function OtherSideFrom(Room: TRoom): TRoom;
- end;
- TDoorNeedingSpell = class(TDoor)
- private
- FSpell: TSpell;
- function TrySpell(Spell: TSpell): boolean;
- public
- constructor Create(room1,room2: TRoom); override;
- destructor Destroy; override;
- //---
- function Enter: Boolean; override;
- end;
- TRoomList = class
- private
- FItemList: TList;
- function GetCount: Integer;
- function GetItems(Index: integer): TRoom;
- protected
- procedure Clear;
- public
- constructor Create;
- destructor Destroy; override;
- //---
- function Add(const Room: TRoom): integer;
- //---
- property Count: Integer read GetCount;
- property Items[Index: integer]: TRoom read GetItems;
- end;
- {迷宫}
- TMaze = class
- private
- FRooms: TRoomList;
- public
- constructor Create;
- destructor Destroy; override;
- //---
- {在迷宫中加入一个房间}
- procedure AddRoom(Room: TRoom);
- {根据房间编号取得房间}
- function RoomNo(RoomNumber: Integer): TRoom;
- end;
- {迷宫构件工厂}
- TMazeFactory = class
- protected
- function MakeDoor(r1,r2: TRoom): TDoor; virtual;
- function MakeMaze: TMaze; virtual;
- function MakeRoom(ARoomNumber: integer): TRoom; virtual;
- function MakeWall: TWall; virtual;
- end;
- {炸弹迷宫构件工厂}
- TBombedMazeFactory = class(TMazeFactory)
- protected
- function MakeRoom(ARoomNumber: integer): TRoom; override;
- function MakeWall(): TWall; override;
- end;
- {魔法迷宫构件工厂}
- TEnchantedMazeFactory = class(TMazeFactory)
- private
- function CastSpell(): TSpell;
- protected
- function MakeRoom(ARoomNumber: integer): TRoom; override;
- function MakeDoor(r1,r2: TRoom): TDoor; override;
- end;
- {迷宫游戏}
- TMazeGame = class
- public
- function CreateMaze(factory: TMazeFactory): TMaze;
- end;
- var
- CurSpell: TSpell;
- implementation
- constructor TRoom.Create(ARoomNumber: integer);
- //---
- procedure _InitSides;
- var
- Direction: TDirection;
- begin
- for Direction := Low(FSides) to High(FSides) do
- FSides[Direction] := nil;
- end;
- begin
- inherited Create;
- //---
- FRoomNumber := ARoomNumber;
- //---
- _InitSides;
- end;
- destructor TRoom.Destroy;
- //---
- procedure _ClearSides;
- var
- Direction: TDirection;
- begin
- for Direction := Low(FSides) to High(FSides) do
- begin
- if FSides[Direction] <> nil then
- FSides[Direction].Free;
- end;
- end;
- begin
- _ClearSides;
- //---
- inherited;
- end;
- function TRoom.Enter: Boolean;
- begin
- self.StateMsg := format('进入房间%d', [FRoomNumber]);
- Result := true;
- end;
- function TRoom.GetSides(Direction: TDirection): TMapSite;
- begin
- Result := FSides[Direction];
- end;
- procedure TRoom.SetSides(Direction: TDirection; const Value: TMapSite);
- begin
- FSides[Direction] := Value;
- end;
- function TWall.Enter: Boolean;
- begin
- self.StateMsg := '碰到墙';
- Result := false;
- end;
- constructor TDoor.Create;
- begin
- inherited Create;
- //---
- Initialize(room1,room2);
- end;
- destructor TDoor.Destroy;
- //---
- procedure _ClearDoor(Room: TRoom);
- var
- Direction: TDirection;
- begin
- if Room <> nil then
- begin
- with Room do
- begin
- for Direction := Low(TDirection) to High(TDirection) do
- begin
- if Sides[Direction] = self then
- begin
- Sides[Direction] := nil;
- exit;
- end;
- end;
- end;
- end;
- end;
- begin
- _ClearDoor(FRoom1);
- _ClearDoor(FRoom2);
- //---
- inherited;
- end;
- function TDoor.Enter: Boolean;
- begin
- self.StateMsg := '碰到门';
- Result := true;
- end;
- procedure TDoor.Initialize(room1,room2: TRoom);
- begin
- FRoom1 := room1;
- FRoom2 := room2;
- FIsOpen := False;
- end;
- function TDoor.OtherSideFrom(Room: TRoom): Troom;
- begin
- if Room = FRoom1 then
- Result := FRoom2
- else
- Result := FRoom1;
- end;
- constructor TBombedWall.Create(Bombed: boolean);
- begin
- inherited Create;
- //---
- Initialize1(Bombed);
- end;
- function TBombedWall.Enter: Boolean;
- begin
- if FBomb then
- begin
- self.StateMsg := '碰到炸弹墙';
- Result := false;
- end
- else
- Result := inherited Enter;
- end;
- procedure TBombedWall.Initialize1(Bombed: boolean);
- begin
- FBomb := Bombed;
- end;
- constructor TDoorNeedingSpell.Create(room1,room2: TRoom);
- begin
- inherited;
- //---
- FSpell := TSpell.Create;
- FSpell.Key := '123';
- end;
- destructor TDoorNeedingSpell.Destroy;
- begin
- FSpell.Free;
- //---
- inherited;
- end;
- function TDoorNeedingSpell.Enter: Boolean;
- begin
- Result := TrySpell(CurSpell);
- if Result then
- self.StateMsg := '碰到门,使用了正确的咒语卷轴'
- else
- self.StateMsg := '碰到门,使用了错误的咒语卷轴';
- end;
- function TDoorNeedingSpell.TrySpell(Spell: TSpell): boolean;
- begin
- Result := FSpell.Key = Spell.Key;
- end;
- constructor TRoomWithABomb.Create(ARoomNumber: integer; Bombed: boolean);
- begin
- inherited Create(ARoomNumber);
- //---
- Initialize1(Bombed);
- end;
- function TRoomWithABomb.Enter: Boolean;
- begin
- if HasBomb then
- begin
- self.StateMsg := format('进入有炸弹的房间%d', [FRoomNumber]);
- Result := true;
- end
- else
- Result := inherited Enter;
- end;
- function TRoomWithABomb.HasBomb: Boolean;
- begin
- Result := FBomb;
- end;
- procedure TRoomWithABomb.Initialize1(Bombed: boolean);
- begin
- FBomb := Bombed;
- end;
- constructor TEnchantedRoom.Create(ARoomNumber: integer; Spell: TSpell);
- begin
- inherited Create(ARoomNumber);
- //---
- FSpell := Spell;
- end;
- destructor TEnchantedRoom.Destroy;
- begin
- if FSpell <> nil then
- FSpell.Free;
- //---
- inherited;
- end;
- function TEnchantedRoom.Enter: Boolean;
- begin
- if HasSpell then
- begin
- CurSpell := PickUpSpell;
- self.StateMsg := format('进入房间%d,拿起咒语卷轴', [FRoomNumber]);
- Result := true;
- end
- else
- Result := inherited Enter;
- end;
- function TEnchantedRoom.HasSpell: boolean;
- begin
- Result := FSpell <> nil;
- end;
- function TEnchantedRoom.PickUpSpell: TSpell;
- begin
- Result := FSpell;
- end;
- constructor TMaze.Create;
- begin
- inherited;
- //---
- FRooms := TRoomList.Create;
- end;
- destructor TMaze.Destroy;
- begin
- FRooms.Free;
- //---
- inherited;
- end;
- procedure TMaze.AddRoom(Room: TRoom);
- begin
- FRooms.Add(Room);
- end;
- function TMaze.RoomNo(RoomNumber: Integer): TRoom;
- var
- i: Integer;
- begin
- Result := nil;
- //---
- with FRooms do
- begin
- for i := 0 to Count - 1 do
- begin
- if Items[i].Roomnumber = RoomNumber then
- begin
- Result := Items[i];
- Exit;
- end;
- end;
- end;
- end;
- function TMazeFactory.MakeDoor(r1,r2: TRoom): TDoor;
- begin
- Result := TDoor.Create(r1,r2);
- end;
- function TMazeFactory.MakeMaze: TMaze;
- begin
- Result := TMaze.Create;
- end;
- function TMazeFactory.MakeRoom(ARoomNumber: integer): TRoom;
- begin
- Result := TRoom.Create(ARoomNumber);
- end;
- function TMazeFactory.MakeWall: TWall;
- begin
- Result := TWall.Create;
- end;
- function TBombedMazeFactory.MakeWall(): TWall;
- begin
- Result := TBombedWall.Create;
- end;
- function TBombedMazeFactory.MakeRoom(ARoomNumber: integer): TRoom;
- begin
- Result := TRoomWithABomb.Create(ARoomNumber);
- end;
- function TEnchantedMazeFactory.MakeRoom(ARoomNumber: integer): TRoom;
- begin
- Result := TEnchantedRoom.Create(ARoomNumber,CastSpell);
- end;
- function TEnchantedMazeFactory.CastSpell(): TSpell;
- begin
- Result := TSpell.Create;
- Result.Key := '123';
- end;
- function TEnchantedMazeFactory.MakeDoor(r1,r2: TRoom): TDoor;
- begin
- Result := TDoorNeedingSpell.Create(r1,r2);
- end;
- function TMazeGame.CreateMaze(factory: TMazeFactory): TMaze;
- var
- aMaze: TMaze;
- r1,r2: Troom;
- theDoor: TDoor;
- begin
- //---建构一个maze,有两个Room,一个Door,六面Wall
- aMaze := factory.MakeMaze;
- //---
- r1 := factory.MakeRoom(1);
- r2 := factory.MakeRoom(2);
- //---
- theDoor := factory.MakeDoor(r1,r2);
- //---
- aMaze.AddRoom(r1);
- aMaze.AddRoom(r2);
- //---
- r1.SetSides(North,factory.MakeWall());
- r1.SetSides(East,theDoor);
- r1.SetSides(South,factory.MakeWall());
- r1.SetSides(West,factory.MakeWall());
- //---
- r2.SetSides(North,factory.MakeWall());
- r2.SetSides(East,factory.MakeWall());
- r2.SetSides(South,factory.MakeWall());
- r2.SetSides(West,theDoor);
- //---
- result := aMaze;
- end;
- constructor TRoomList.Create;
- begin
- inherited;
- //---
- FItemList := TList.Create;
- end;
- destructor TRoomList.Destroy;
- begin
- Clear;
- FItemList.Free;
- //---
- inherited;
- end;
- function TRoomList.Add(const Room: TRoom): integer;
- begin
- if Assigned(Room) then
- Result := FItemList.Add(Room)
- else
- Result := -1;
- end;
- procedure TRoomList.Clear;
- var
- i: Integer;
- begin
- with FItemList do
- begin
- for i := 0 to Count - 1 do
- TObject(Items[i]).Free;
- //---
- Clear;
- end;
- end;
- function TRoomList.GetCount: Integer;
- begin
- Result := FItemList.Count;
- end;
- function TRoomList.GetItems(Index: integer): TRoom;
- begin
- Result := FItemList[Index];
- end;
- end.
- unit Unit2;
- interface
- uses
- Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
- Dialogs,StdCtrls,uMazeFactory;
- type
- TForm2 = class(TForm)
- ListBox1: TListBox;
- procedure FormDestroy(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
- procedure ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
- private
- FMazeGame: TMazeGame;
- FMazeFactory: TMazeFactory;
- FMaze: TMaze;
- FCurRoom: TRoom;
- public
- { Public declarations }
- end;
- var
- Form2: TForm2;
- implementation
- {$R *.dfm}
- procedure TForm2.FormCreate(Sender: TObject);
- begin
- self.KeyPreview := true;
- //---
- FMazeGame := TMazeGame.Create;
- //---
- {FMazeFactory := TMazeFactory.Create;
- FMaze := FMazeGame.CreateMaze(FMazeFactory); }
- //---
- FMazeFactory := TBombedMazeFactory.Create;
- FMaze := FMazeGame.CreateMaze(FMazeFactory);
- TRoomWithABomb(FMaze.RoomNo(2)).Initialize1(true);
- //---
- {FMazeFactory := TEnchantedMazeFactory.Create;
- FMaze := FMazeGame.CreateMaze(FMazeFactory);}
- //---
- FCurRoom := FMaze.RoomNo(1);
- with FCurRoom do
- begin
- Enter;
- ListBox1.Items.Add(StateMsg);
- end;
- end;
- procedure TForm2.FormDestroy(Sender: TObject);
- begin
- FMaze.Free;
- FMazeFactory.Free;
- FMazeGame.Free;
- end;
- procedure TForm2.FormKeyDown(Sender: TObject; var Key: Word; Shift:
- TShiftState);
- //---
- procedure _EnterRoomSide(Direction: TDirection);
- var
- ARoom: TRoom;
- begin
- with FCurRoom do
- begin
- if Sides[Direction] <> nil then
- begin
- with Sides[Direction] do
- begin
- if Enter then
- begin
- ListBox1.Items.Add(DirectionNames[Direction] + ':' + StateMsg);
- //---
- if Sides[Direction] is TDoor then
- begin
- ARoom := TDoor(Sides[Direction]).OtherSideFrom(FCurRoom);
- if ARoom <> nil then
- begin
- if ARoom.Enter then
- FCurRoom := ARoom;
- ListBox1.Items.Add(ARoom.StateMsg);
- end;
- end;
- end
- else
- ListBox1.Items.Add(DirectionNames[Direction] + ':' + StateMsg);
- end;
- end;
- end;
- end;
- begin
- case Ord(Key) of
- VK_LEFT: _EnterRoomSide(East);
- VK_RIGHT: _EnterRoomSide(West);
- VK_UP: _EnterRoomSide(South);
- VK_DOWN: _EnterRoomSide(North);
- end;
- end;
- procedure TForm2.ListBox1KeyDown(Sender: TObject; var Key: Word; Shift:
- TShiftState);
- begin
- Key := 0;
- end;
- end.
这篇关于《GOF设计模式》—抽象工厂(Abstract Factory)—Delphi源码示例:基于抽象工厂的迷宫的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!