创建型模式抽象了实例化过程。他们帮助一个熊独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象。
随着系统演化得越来越依赖于对象复合而不是类继承,创建型模式变得更为重要。在这些模式中有两个不断出现的主旋律。第一,他们都将关于该系统使用那些具体的类的信息封装起来。第二,它们隐藏了这些类的实例是如何被创建和放在一起的。
这一章,我们将以一个迷宫游戏为背景,完成,Abstract factory(抽象工厂),Builder(生成器),Factory method(工厂方法),prototype(原型),Singleton(单件)5中设计模式的学习。首先,我们先描述一下迷宫游戏的背景和最初的设计
首先,我们定义了一个枚举类型,用来指示房间的方向:
public enum Direction { North, South, West, East }
定义一个迷宫组件的公共抽象类MapSite。MapSite仅定义了一个操作,它的含义决定于你在进入什么。如果你进入一个房间,那么你的文章会发生改变,如果你试图进入一扇门,那么这两件事中就有一件要发生:如果们是开这段,你进入另一个房间。如果们是关着的,那么你就会碰壁。
public abstract class MapSite { public abstract void Enter(); }
Room是MapSite的一个具体的子类,而MapSite定义了迷宫中构件之间的主要关系。Room有指向其他MapSite对象的引用,并保存一个房间号,这个数字用来标示迷宫中飞房间。
public class Room : MapSite { private int _RoomNumber; private List<MapSite> _MapSiteList; public Room(int roomNumber) { _RoomNumber = roomNumber; _MapSiteList = new List<MapSite>(); } public override void Enter() { } public MapSite GetSide(Direction direction) { switch (direction) { case Direction.North: return _MapSiteList[0]; case Direction.South: return _MapSiteList[1]; case Direction.West: return _MapSiteList[2]; case Direction.East: return _MapSiteList[3]; } return null; } public void SetSide(Direction dirction, MapSite mapSite) { switch (dirction) { case Direction.North: _MapSiteList[0] = mapSite; break; case Direction.South: _MapSiteList[1] = mapSite; break; case Direction.West: _MapSiteList[2] = mapSite; break; case Direction.East: _MapSiteList[3] = mapSite; break; } } }
public class Wall : MapSite { public Wall() { } public override void Enter() { }
public class Door : MapSite { private Room _Room1; private Room _Room2; private bool _IsOpen; public Door(Room room1, Room room2) { _Room1 = room1; _Room2 = room2; } public override void Enter() { } } }
再定义一个用来表示房间集合的Maze类。
public class Maze { public Maze() { } public void AddRoom(Room room) { } public Room RoomNumber(int roomNumber) { return null; } }
然后我们再定义一个类时MazeGame,由他来创建迷宫。
public class MazeGame { public MazeGame() { } public Maze CreateMazeGame() { Maze maze = new Maze(); Room r1 = new Room(1); Room r2 = new Room(2); Door theDoor = new Door(r1, r2); maze.AddRoom(r1); maze.AddRoom(r2); r1.SetSide(Direction.North,new Wall()); r1.SetSide(Direction.East,theDoor); r1.SetSide(Direction.South, new Wall()); r1.SetSide(Direction.West, new Wall()); r2.SetSide(Direction.North, new Wall()); r2.SetSide(Direction.East, new Wall()); r2.SetSide(Direction.South, new Wall()); r2.SetSide(Direction.West, theDoor); return maze; } }
上面的编码是最初的设计,当需求发生变化时,我们看看如何利用我们的设计模式来更好的解决问题。
首先,我们先概括的说一下未来5中设计模式在这个迷宫游戏中的使用:
- 如果CreateMaze调用虚函数而不是构造器来创建它需要的房间、墙壁和门,那么你可以创建一个MazeGame的子类并重定义这些虚函数,从而被实例化的类。这个一方法是Factory Method模式的一个例子。
- 如果传递一个对象给CreateMaze做为参数来创建房间、墙壁和门,那么你可以传递不同的参数来改变房间、墙壁和门的类,这是Abstract Factory模式的一个例子
- 粗犷传递一个对象给CreateMaze,这个对象可以在它所创建的迷宫中使用增加房间、墙壁和门的操作,来全面创建一个新的迷宫,那么你可以使用继承来改变迷宫的一下部分或该迷宫被创建的方式。这是Builder模式的一个例子。
- 如果CreateMaze由多种原型的房间、墙壁和门对象参数化,它拷贝并将这些对象增加到迷宫中,那么你可以用不同的对象踢馆这些原型对象以改变迷宫的构造。这是Prototype模式的一个例子。
- Singleton模式,可以保证每个游戏中仅有一个迷宫而且所有的游戏对象都可以迅速访问它-不需要求助于全局变量或函数。
这些就是对整个创建型模式的总括,这里的迷宫游戏是最初的设计,我们在学习以后模式的过程中逐渐的修改这个迷宫程序。下面给出这没有实现的迷宫代码。
代码下载:MazeGame.rar