《设计模式》学习笔记(3)——一个学习创建型模式的例子

又有好久没学习了 lol.gif,而且看书也比较散漫,随手翻到哪里就看到哪里 icon10.gif,所以写的学习笔记也比较乱。闲话少说,进入正题。

为什么会有这个例子?
由于创建型模式紧密相关,因此将5个创建型模式以同一个例子来研究更容易说明它们的相似点和相异点。

例子:为一个电脑游戏创建一个迷宫。这个迷宫和游戏可能会随着模式的不同而有所区别:有时候仅仅需要找到一个迷宫的出口;而有时候迷宫可能包括一些要解决的问题等等。

由于首先研究创建型模式,因此我们目前只关心迷宫是怎样被创建的,而不用去关心其他的细节。我们将迷宫定义为一系列的房间,每个房间都知道它的邻居:要么是房间,要么是墙,再要么是通往另一个房间的一扇门。

因此这里将会有三个类:Room, Door和Wall,此外我们还应该关心一下方向,因为一个人站在房间里会有四个方向可以移动,那么就会有一个Direction枚举。

None.gif namespace  My.Reading.DesignPatterns.MazeGame
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Direction in the maze.
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public enum Direction
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        North,
InBlock.gif        South,
InBlock.gif        East,
InBlock.gif        West
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}


另外,我们可能还需要一个地图,地图上会标明已经探索过的一些元素,如Room或者Wall,因此我们给出一个迷宫元素的基类:MapSite,为了方便,我们给它简单定义一个操作Enter,表示你进入了一个迷宫的元素。下面是他们的关系图及一部分代码:(注:代码仅仅是为了说明,本身无任何意义)

example.JPG 

None.gif namespace  My.Reading.DesignPatterns.MazeGame
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Public abstract class for all of the maze's components.
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public abstract class MapSite
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public MapSite()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Decide what you are going to.
InBlock.gif        
/// For example: If you are going to a door, one of the two things will happen:
InBlock.gif        
/// 1. if the door is open, you will enter another room;
InBlock.gif        
/// 2. if the door is closed, you will hit the wall.
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public abstract void Enter();
InBlock.gif
InBlock.gif        
public abstract void ShowSelfInformation();
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public class Door : MapSite
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private Room room1;
InBlock.gif        
private Room room2;
InBlock.gif        
private bool isOpen = false;
InBlock.gif
InBlock.gif        
public Door(Room room1, Room room2)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.room1 = room1;
InBlock.gif            
this.room2 = room2;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public Room OtherSideFrom(Room room)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new NotImplementedException();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public override void Enter()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (isOpen)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//dot.gif
ExpandedSubBlockEnd.gif
            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//dot.gif
ExpandedSubBlockEnd.gif
            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public override void ShowSelfInformation()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"I am the normal door in namespace MazeGame!");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif    
public class Room : MapSite
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private int roomNo;
InBlock.gif        
private MapSite[] sides = new MapSite[4];
InBlock.gif
InBlock.gif        
public Room(int roomNo)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.roomNo = roomNo;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int RoomNo
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return roomNo;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public MapSite GetSide(Direction direction)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
switch (direction)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
case Direction.North:
InBlock.gif                    
return sides[0];
InBlock.gif
InBlock.gif                
case Direction.East:
InBlock.gif                    
return sides[1];
InBlock.gif
InBlock.gif                
case Direction.South:
InBlock.gif                    
return sides[2];
InBlock.gif
InBlock.gif                
case Direction.West:
InBlock.gif                    
return sides[3];
InBlock.gif
InBlock.gif                
default:
InBlock.gif                    
return null;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void SetSide(Direction direction, MapSite mapSite)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
switch (direction)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
case Direction.North:
InBlock.gif                    sides[
0= mapSite;
InBlock.gif                    
break;
InBlock.gif
InBlock.gif                
case Direction.East:
InBlock.gif                    sides[
1= mapSite;
InBlock.gif                    
break;
InBlock.gif
InBlock.gif                
case Direction.South:
InBlock.gif                    sides[
2= mapSite;
InBlock.gif                    
break;
InBlock.gif
InBlock.gif                
case Direction.West:
InBlock.gif                    sides[
3= mapSite;
InBlock.gif                    
break;
InBlock.gif
InBlock.gif                
default:
InBlock.gif                    
break;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public override void Enter()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//dot.gif
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif        
public override void ShowSelfInformation()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"I am the normal room in namespace MazeGame!");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif    
public class Maze
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private ArrayList rooms = new ArrayList();
InBlock.gif
InBlock.gif        
public Maze()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int Count
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return rooms.Count;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void AddRoom(Room room)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            rooms.Add(room);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Get a room from it's number.
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public Room RoomNo(int roomNo)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Room room 
= null;
InBlock.gif
InBlock.gif            
for (int i = 0; i < rooms.Count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                room 
= rooms[i] as Room;
InBlock.gif
InBlock.gif                
if (room.RoomNo == roomNo)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
break;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
return room;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif}

由于Wall类比较简单,因此就不再占用篇幅。至此为止我们定义完了迷宫,下一步我们将要在游戏中生成一个迷宫。一个最直接最简单同时也是最常用的方法就是进行硬编码:

None.gif namespace  My.Reading.DesignPatterns.MazeGame
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public class MazeGame
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public MazeGame()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public Maze CreateMaze()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Maze aMaze 
= new Maze();
InBlock.gif            Room r1 
= new Room(1);
InBlock.gif            Room r2 
= new Room(2);
InBlock.gif            Door theDoor 
= new Door(r1, r2);
InBlock.gif
InBlock.gif            aMaze.AddRoom(r1);
InBlock.gif            aMaze.AddRoom(r2);
InBlock.gif
InBlock.gif            r1.SetSide(Direction.North, 
new Wall());
InBlock.gif            r1.SetSide(Direction.East, theDoor);
InBlock.gif            r1.SetSide(Direction.South, 
new Wall());
InBlock.gif            r1.SetSide(Direction.West, 
new Wall());
InBlock.gif
InBlock.gif            r2.SetSide(Direction.North, 
new Wall());
InBlock.gif            r2.SetSide(Direction.East, 
new Wall());
InBlock.gif            r2.SetSide(Direction.South, 
new Wall());
InBlock.gif            r2.SetSide(Direction.West, theDoor);
InBlock.gif
InBlock.gif            
return aMaze;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

这样,我们生成了一个很简单的迷宫,它仅仅由两个房间以及它们之间的一扇门组成。

现在假设我们有一个新游戏,需要重用上面已有的迷宫布局,但是迷宫中的门是有锁的,需要钥匙才可以打开。很显然,上面的硬编码实现将导致CreateMaze很难重用,于是创建型模式便要登场了。

转载于:https://www.cnblogs.com/gamix/archive/2005/04/07/132996.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值