博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《GOF设计模式》—工厂方法(Factory Method)—Delphi源码示例:基于工厂方法的迷宫
阅读量:2066 次
发布时间:2019-04-29

本文共 14328 字,大约阅读时间需要 47 分钟。

示例:基于工厂方法的迷宫实现:.函数CreateMaze建造并返回一个迷宫。这个函数存在的一个问题是它对迷宫、房间、门和墙壁的类进行了硬编码。我们将引入工厂方法以使子类可以选择这些构件。首先,我们将在MazeGame中定义工厂方法以创建迷宫、房间、墙壁和门对象;每一个工厂方法返回一个给定类型的迷宫构件。MazeGame提供一些缺省的实现,它们返回最简单的迷宫、房间、墙壁和门。不同的游戏可以创建MazeGame的子类以特别指明一些迷宫的部件。MazeGame子类可以重定义一些或所有的工厂方法以指定产品中的变化。例如,一个BombedMazeGame可以重定义产品Room和Wall以返回爆炸后的变体。代码: unit uMaze; 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;    {迷宫游戏}    TMazeGame = class    protected        function MakeMaze: TMaze; virtual;        function MakeRoom(ARoomNumber: integer): TRoom; virtual;        function MakeWall: TWall; virtual;        function MakeDoor(r1,r2: TRoom): TDoor; virtual;    public        function CreateMaze: TMaze;    end;    {炸弹迷宫游戏}    TBombedMazeGame = class(TMazeGame)    protected        function MakeRoom(ARoomNumber: integer): TRoom; override;        function MakeWall(): TWall; override;    end;    {魔法迷宫游戏}    TEnchantedMazeGame = class(TMazeGame)    private        function CastSpell(): TSpell;    protected        function MakeRoom(ARoomNumber: integer): TRoom; override;        function MakeDoor(r1,r2: TRoom): TDoor; override;    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.Intialize(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.Intialize(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 TMazeGame.CreateMaze: TMaze;var    aMaze: TMaze;    r1,r2: Troom;    theDoor: TDoor;begin    //---建构一个maze,有两个Room,一个Door,六面Wall    aMaze := MakeMaze;    //---    r1 := MakeRoom(1);    r2 := MakeRoom(2);    //---    theDoor := MakeDoor(r1,r2);    //---    aMaze.AddRoom(r1);    aMaze.AddRoom(r2);    //---    r1.SetSides(North,MakeWall());    r1.SetSides(East,theDoor);    r1.SetSides(South,MakeWall());    r1.SetSides(West,MakeWall());    //---    r2.SetSides(North,MakeWall());    r2.SetSides(East,MakeWall());    r2.SetSides(South,MakeWall());    r2.SetSides(West,theDoor);    //---    result := aMaze;end; function TMazeGame.MakeMaze: TMaze;begin    Result := TMaze.Create;end; function TMazeGame.MakeRoom(ARoomNumber: integer): TRoom;begin    Result := TRoom.Create(ARoomNumber);end; function TMazeGame.MakeWall: TWall;begin    Result := TWall.Create;end; function TMazeGame.MakeDoor(r1,r2: TRoom): TDoor;begin    Result := TDoor.Create(r1,r2);end; function TBombedMazeGame.MakeWall(): TWall;begin    Result := TBombedWall.Create;end; function TBombedMazeGame.MakeRoom(ARoomNumber: integer): TRoom;begin    Result := TRoomWithABomb.Create(ARoomNumber);end; function TEnchantedMazeGame.MakeRoom(ARoomNumber: integer): TRoom;begin    Result := TEnchantedRoom.Create(ARoomNumber,CastSpell);end; function TEnchantedMazeGame.CastSpell(): TSpell;begin    Result := TSpell.Create;    Result.Key := '123';end; function TEnchantedMazeGame.MakeDoor(r1,r2: TRoom): TDoor;begin    Result := TDoorNeedingSpell.Create(r1,r2);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 Unit1; interface uses    Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,    Dialogs,StdCtrls,Menus,uMaze; type    TForm1 = class(TForm)        ListBox1: TListBox;        procedure FormCreate(Sender: TObject);        procedure FormDestroy(Sender: TObject);        procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);        procedure ListBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);    private        FMazeGame: TMazeGame;        FMaze: TMaze;        FCurRoom: TRoom;    public    { Public declarations }    end; var    Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject);begin    self.KeyPreview := true;    //---    {FMazeGame := TMazeGame.Create;    FMaze := FMazeGame.CreateMaze;}    //---    {FMazeGame := TBombedMazeGame.Create;    FMaze := FMazeGame.CreateMaze;    TRoomWithABomb(FMaze.RoomNo(2)).Initialize1(true);}    //---    FMazeGame := TEnchantedMazeGame.Create;    FMaze := FMazeGame.CreateMaze;    //---    FCurRoom := FMaze.RoomNo(1);    with FCurRoom do    begin        Enter;        ListBox1.Items.Add(StateMsg);    end;end; procedure TForm1.FormDestroy(Sender: TObject);begin    FMaze.Free;    FMazeGame.Free;end; procedure TForm1.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 TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word; Shift:    TShiftState);begin    Key := 0;end; end.

转载地址:http://guymf.baihongyu.com/

你可能感兴趣的文章
剑指offer 27.二叉树的深度
查看>>
剑指offer 29.字符串的排列
查看>>
剑指offer 31.最小的k个树
查看>>
剑指offer 32.整数中1出现的次数
查看>>
剑指offer 33.第一个只出现一次的字符
查看>>
剑指offer 34.把数组排成最小的数
查看>>
剑指offer 35.数组中只出现一次的数字
查看>>
剑指offer 36.数字在排序数组中出现的次数
查看>>
剑指offer 37.数组中重复的数字
查看>>
剑指offer 38.丑数
查看>>
剑指offer 39.构建乘积数组
查看>>
剑指offer 57. 删除链表中重复的结点
查看>>
剑指offer 58. 链表中环的入口结点
查看>>
剑指offer 59. 把字符串转换成整数
查看>>
剑指offer 60. 不用加减乘除做加法
查看>>
leetcode 热题 Hot 100-3. 合并两个有序链表
查看>>
leetcode 热题 Hot 100-4. 对称二叉树
查看>>
Leetcode C++《热题 Hot 100-12》226.翻转二叉树
查看>>
Leetcode C++《热题 Hot 100-13》234.回文链表
查看>>
Leetcode C++《热题 Hot 100-14》283.移动零
查看>>