本书设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好,表达清楚的软件设计模式,这些模式在实用环境下有特别有用
10. 代码示例我们将使用Abstract Factory模式创建我们在这章开始所讨论的迷宫。类M a z e F a c t o r y可以创建迷宫的组件。它建造房间、墙壁和房间之间的门。它可以用于一
个从文件中读取迷宫说明图并建造相应迷宫的程序。或者它可以被用于一个随机建造迷宫的程序。建造迷宫的程序将 M a z e F a c t o r y作为一个参数,这样程序员就能指定要创建的房间、墙壁和门等类。
回想一下建立一个由两个房间和它们之间的门组成的小迷宫的成员函数 C r e a t e M a z e。 C r e a
t e M a z e对类名进行硬编码,
这使得很难用不同的组件创
建迷宫。
这里是一个以M a z e F a c t
o r y为参数的新版本的
CreateMaze ,它修改了以上
缺点:
我们创建M a z e F a c t o r y
的子类E n c h a n t e d M a z e F a c t o r y,这是一个创建施了魔法的迷宫的工厂。E n c h a n t e d M a z e F a c t o r y将重定义不同的成员函数并返回 R o o m,Wa l l等不同的子类。
本书设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好,表达清楚的软件设计模式,这些模式在实用环境下有特别有用
现在假设我们想生成一个迷宫游戏,在这个游戏里,每个房间中可以有一个炸弹。如果这个炸弹爆炸,它将(至少)毁坏墙壁。我们可以生成一个 R o o m的子类以明了是否有一个炸弹在房间中以及该炸弹是否爆炸了。我们也将需要一个 Wa l l的子类以明了对墙壁的损坏。我们将称这些类为R o o m Wi t h A B o m b和B o m b e d Wa l l。
我们将定义的最后一个类是 B o m b e d M a z e F a c t o r y,它是M a z e F a c t o r y的子类,保证了墙壁是B o m b e d Wa l l类的而房间是R o o m Wi t h A B o m b的。B o m b e d M a z e F a c t o r y仅需重
定义两个函数:
为建造一个包含炸弹的简单迷
宫,我们仅用 B o m b e d M a z
MazeGame game; BombedMazeFactory factory;
g a m e . C r e a t e M a z e ( f a c t o r y ) ; e F a c t o r y调用C r e a t e M a z e。
C r e a t e M a z e也可以接收一个E n c h a n t e d M a z e F a c t o r y实例来建造施了魔法的迷宫。 注意M a z e F a c t o r y仅是工厂方法的一个集合。这是最通常的实现 Abstract Factory模式的方式。同时注意 M a z e F a c t o r y不是一个抽象类;因此它既作为 A b s t r a c t F a c t o r y也作为 C o n c r e t e F a c t o r y。这是 Abstract Factory模式的简单应用的另一个通常的实现。因为 M a z e F a c t o r y是一个完全由工厂方法组成的具体类,通过生成一个子类并重定义需要改变的操作,它很容易生成一个新的 M a z e F a c t o r y。
C r e a t e M a z e使用房间的S e t S i d e操作以指定它们的各面。如果它用一个 B o m b e d M a z e F a c t o r y创建房间,那么该迷宫将由有 B o m b e d Wa l l面的 R o o m Wi t h A B o m b对象组成。如果 R o o m Wi t h A B o m b必须访问一个B o m b e d Wa l l的与特定子类相关的成员,那么它将不得不对它的墙壁引用以进行从 Wa l l *到B o m b e d Wa l l *的转换。只要该参数确实是一个 B o m b e d Wa l l,这个向下类型转换就是安全的,而如果墙壁仅由一个 B o m b e d M a z e F a c t o r y创建就可以保证这一点。
当然,像S m a l l t a l k这样的动态类型语言不需要向下类型转换,但如果它们在应该是 Wa l l的子类的地方遇到一个 Wa l l类可能会产生运行时刻错误。使用 Abstract Factory建造墙壁,通过确定仅有特定类型的墙壁可以被创建,从而有助于防止这些运行时刻错误。
让我们考虑一个S m a l l t a l k版本的M a z e F a c t o r y,它仅有一个以要生成的对象种类为参数的 m a k e操作。此外,具体工厂存储它所创建的产品的类。
首先,我们用S m a l l t a l k写一个等价的C r e a t e M a z e: