首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

20.点缀作战map——享元模式

2012-07-31 
20.点缀作战地图——享元模式周一的早上,精力充沛(这是因为周日没有加班),随时准备迎接新的挑战。挑战马上就

20.点缀作战地图——享元模式
周一的早上,精力充沛(这是因为周日没有加班),随时准备迎接新的挑战。

挑战马上就到。

为了展现战争的巨大破坏力量,老板决定在地图上添加大量的残垣断壁单位,这样可以让战场景象更真实。听说你创建了游戏中的各种单位,这个工作只好又交给你了。

 第一个方案

现在,你首先在EUnit枚举中添加了新的成员:

''游戏单位标识枚举

Public Enum EUnit

    ...

    Debris = 5004 '残骸

End Enum

(项目:FlyweightPatternDemo    文件:Enums.vb)

 

接下来着手继承CUnit单位;创建CDebris类,就像这样:

Public Class CDebris

    Inherits CUnit

    Public Sub New()

        myBehavior = New CNoBehavior

        myWeapon = New CNoWeapon

        mySpeed = 0

        UnitId = EUnit.Debris

    End Sub

End Class

(项目:FlyweightPatternDemo    文件:CDebris.vb)

 

最后,在CBuildUnitCreator类中添加这个单位的创建代码就好了:

''建筑物单位创建者

Public Class CBuildUnitCreator

    Inherits CUnitCreator

    Public Overrides Function CreateUnit(ByVal unitType As EUnit) As IUnit

        Select Case unitType

            ...

            Case EUnit.Debris

                Return New CDebris

            ...

        End Select

    End Function

End Class

(项目:FlyweightPatternDemo    文件:Creator.vb)

 

一些都是模式化的,修改起来非常简单,又是不到10分钟,你就将代码提交了,看来这次不会有什么问题了,地图团队的那帮人一定得请你吃午饭。

但是(我也不喜欢但是),项目经理很快又过来了。

“关于新的单位‘残垣断壁’们,有一些问题。”

l         你只设计了一种残骸的枚举成员,也就是说只能有一种残垣断壁,这不可能,战场上应该有各式各样的建筑物和其它类型的残骸,比如汽车、飞机、工厂等等。

l         作战单位已经创建了太多的对象,而这些残骸又不能动,又不能作为其他单位的掩体;它们只是显示在那儿就行了,不用浪费这么多资源去创建对象。

l         这个功能是地图模块的,而不是作战单位模块;你应该把显示这些单位的代码放到CMapManager类中;比如,在CMapManager类中创建一个ShowDebris()的方法,让它们随机分布就行了。

l         还有一点,作战单位如果觉得这些东西挡路,可以把它们轰掉。

 

问题还真多!只能重新设计了。“设计模式!赐予我力量吧!”

好吧,我们使用享元模式(Flyweight Patterns)。

 使用享元模式

享元模式(Flyweight Pattern),又称为蝇量模式,它的定义是:运用共享技术有效地支持大量“轻量级”的对象;使用享元模式时,我们只创建一个实例来管理大量的虚拟对象,比如本例中的那些残垣断壁。

地图组的CMapManager类代码下载过来了,你不能修改任何原有代码,只能添加Debris相关的代码。在这期间,CMapManager类将被代码管理系统锁定,所以你得抓紧时间,不然,地图团队的那帮人就有理由去喝茶了。

 

我们先来解决第一个问题,多种Debris,现在我们创建一个EDebris枚举,用于定义多种类型的残骸类型,它的定义如下:

Public Enum EDebris

    HouseA = 9001

    HouseB = 9002

    CarA = 9003

    CarB = 9004

End Enum

(项目:FlyweightPatternDemo    文件:Enums.vb)

 

第二个问题,虽然这些Debris单位不能有什么动作,但它们还是应该有一些信息,比如位置、类型标识、名称,以及“生命值”等;不创建类,我们可以创建一个结构来表示它们,定义如下:

Public Structure SDebris

    Public X As Integer

    Public Y As Integer

    Public Name As String

    Public UnitId As EDebris

    Public Life As Integer

    '测试用,显示信息

    Public Sub ShowInfo()

        Console.WriteLine("{0}  类型:{1}  位置:({2}, {3})  生命值:{4}", _

                          Name, UnitId, X, Y, Life)

    End Sub

End Structure

(项目:FlyweightPatternDemo    文件:Structures.vb)

 

好吧,现在我们打开CMapManager类,添加显示这些Debris单位的代码:

Public Class CMapManager

    Private r As New Random '随机数产生器

    Const ScreenWidth As Integer = 800 '屏幕宽度(像素)

    Const ScreenHeight As Integer = 600 '屏幕高度(像素)

    Const DebrisNumber As Integer = 6 '多少个Debris单位

    Const DebrisTypeMin As Integer = 9001 'Debris单位类型

    Const DebrisTypeMax As Integer = 9004 + 1

    Protected arrDebris(DebrisNumber - 1) As SDebris '创建的Debris单位

    Public Sub ShowDebris()

        Dim i, iMax As Integer

        iMax = DebrisNumber - 1

        For i = 0 To iMax

            With arrDebris(i)

                .X = r.Next(0, ScreenWidth)

                .Y = r.Next(0, ScreenHeight)

                .UnitId = r.Next(DebrisTypeMin, DebrisTypeMax)

                .Name = "Debris_" & i.ToString

                .Life = r.Next(10, 50)

                '测试,显示信息

                .ShowInfo()

            End With

        Next

    End Sub

End Class

(项目:FlyweightPatternDemo    文件:CMapManager.vb)

 

在这个示例中,我们没有为Debris单位创建实例,只是借用CMapManager类进行统一的管理,这些Debris单位的信息保存在arrDebris数组中;现在,我们使用如下代码进行测试:

Module Module1

    Sub Main()

        '显示一张作战地图

        Dim map As New CMapManager

        map.ShowDebris()

        Console.ReadLine()

    End Sub

End Module

(项目:FlyweightPatternDemo    文件:Module1.vb)

 

本例运行结果如下图:

 

好了,任务完成了,我们在地图中随机分布了6(DebrisNumber)个Debris单位,并没有创建新的Debris单位对象;它们的数据存在于一个地图类(CMapManager)的实例中,因为它们本来就是地图场景的一部分。

最后一个问题,如果Debris单位的生命值被轰成了0,在下一个游戏循环中不再显示它就是了。

 小结

这就是享元模式(Flyweight Pattern),我们使用一个实例管理多个虚拟对象;有效地减少了对象数量,节省运行时的系统资源开销。此模式在使用相同或相似的方法操作多个对象时非常有效,但对于逻辑较复杂的对象,如游戏中的作战单位,就不太适合。

 

出自:http://www.caohuayu.com/books/B0003/B0003.aspx

热点排行