by  高煥堂:misoo.tw@qq.com

 

1.  复习<主板、插件、配件>模式

   在《主板模式与平台碎片》文章里已经说明了,我们可以将主板模式扩大为<主板、插件、配件>模式。于此,我们再复习一下。这个扩充型的主板模式,其结构如下图:

 

  基于主板模式,订定通用性<I>接口,有效将SurfaceView与Camera两者之间的相依性(Dependency)降低,成为疏结合(Loosely Coupled)关系。从SurfaceView的角度而言,它透过Callback接口整合了myPicture小碎片,然后透过myPicture将SurfaceHolder本身的接口传递给Camera大碎片。于是,Camera取得了SurfaceHolder的接口,就能藉由这接口而调用到SurfaceHolder里的函数,将影像传递给SurfaceView了。

   由于Camera大碎片的接口被写在myPicture里,而不是写在SurfaceView或SurfaceHolder里,所以抽换掉Camera碎片时,只需要改写myPicture的代码即可,而不会影响到SurfaceView或SurfaceHolder。因此大幅降低了SurfaceView/SurfaceHolder与Camera两者之间的相依性,也就打幅提升了Camera大碎片的抽换性(互换性)。

    一旦SurfaceView与Camera两者变成为疏结合关系了,当业主在稍后改变了心意时,可以再度做弹性的抽换碎片了,也就是呈现了高度的互换性。例如,委托App开发者把 SurfaceView联接到OpenGL绘图引擎上。如下图所示:

 

  基于这个<主板、插件、配件>模式,App可使用SurfaceView来显示3D的动态绘图。软件主板模式是架构师用来包容未来变化的尚方宝剑。具有这种优越架构的智能型产品,就具备良好的抽换性和未来性,更能掌握美好的商机。 

 

 2.  业务型主板与碎片 

   --Android的「拉霸游戏机」为例

   拉霸机(Slot Machine,简称SM)是大家常玩的游戏机,其造型有许多种,例如Android水果盘拉霸机,其画面如下图: 

      

       其玩法是先输入投注金额(Bet),然后拉动点击把手或点击<SPIN>钮来转动滚动条,滚动条会各自转动,然后随机出现不同图案,如果停定时,有出现符合相同或特定相同图案联机者,即依其赔率而胜出。同一家游戏场里的拉霸机通常会联网,以投注额厘定累积大奖(Jackpot)金额,并随时更新累绩大奖金额,以便增加吸引性。这游戏软件可分为两部分:

  •  游戏(Game)端部分,也就是Android手机端的应用对象。
  •  柜台(Console)端部分,也就是GAE云层Servlet对象。 

       当玩家押注后,按下<SPIN> 按钮(开始加速滚动),游戏端就将「目前余额」和「押注金额」传送给GAE的柜台端对象。等待柜台端对象计算出中奖金额后,将「新余额」和「奖项级别」回传给Android游戏端(滚动开始减速),并更新游戏端的画面。其中,Android游戏端对象(ac01.java)发送HTTP来呼叫GAE云层的Servlet接口,如下图所示:

  

  如果你是游戏机的厂商,你通常会把GAE Console(即Game云服务)视为<碎片>,希望游戏机与云服务之间相依性下降,提升Game云服务的抽换性,可获得更多的销售机会。如下图:

    

 

     为了实现抽换性,最有效的途径就是采取主板模式,来建立游戏的<业务主板>,如下图:

 

  Android游戏端透过HTTP和Servlet接口来传送三种讯息给GAE 云层。

这三种讯息为: 

  • 当玩家启动Android游戏端时,发送"Init:"讯息给GAE云层对象。GAE就从DB里读取玩家的余额(即上回的余额),并回传给游戏端。
  • 当玩家按下<SPIN>按钮时,发送"Bett:amount,bet" 讯息给GAE云对象。此讯息附有余额(amount)和押注金额(bet),要求GAE对象决定「奖项级别(Rank)」,计算奖金和新余额,然后回传给游戏端。
  • 当玩家欲结束时,按下<Exit>按钮发送"Fini:amount"讯息给GAE云层。此讯息附有目前余额(amount),GAE接到讯息,就依据将余额存入DB,完成时立即回复给游戏端,关闭游戏端画面。 

 

   基于上一小节所提到的抽换性概念,我们必须将其<游戏机>端与<云端>两者的相依性降低,让两者之间成为疏结合(Loosely Coupled)关系。这样可以让业主有决策的空间:业主可已决定采用那一种云端服务。于是,可以画出框架需求图如下: 

  

   于是,架构师将游戏机端与与云端两者的相依性降低,成为疏结合,预留了弹性,让业主在稍后出现时,能有决策的空间,并委托App开发者把其决策写在App子类别里。如下图所示: 

 

    于是,架构师将游戏机端与与云端两者的相依性降低,成为疏结合,预留了弹性,让业主在稍后出现时,能有决策的空间,并委托App开发者把其决策写在App子类别里。这整体架构是由两个主板模式所组合而成的架构。如下图所示: 

  为了实现上述目标,就必须让业主(委托 App开发者)把其决策写在AP子类别里,然后设计框架接口(如IGame)来与框架基类(如GameView)相衔接。当这个拉霸机游戏软件框架与云端服务软件分离了之后,就能将此框架(软件)与拉霸游戏机(硬件)两者整合在一起,成为一项软硬整合产品了,软硬件可以一起销售了。

    如果有些业主(如赌场)早已经有了云层服务端了,上述的软硬整合产品就很容易卖进去。因此EIT框架开发思维,非常有益于软硬整合产品开发,也非常有助于销售、开拓市场。预留空间给业主做决策是架构师的职责,而应该预留多大的空间,则是架构师对于未来性的洞悉力和技能了。例如,架构师可以决定预留更大空间,如下图: 

 

   因为要让业主挑选或自行设计UI,框架就必须将SurfaceView的画布(Canvas or Surface)传递给AP子类别,所以必须修改IGame接口,增添一个函数(如setHolder()函数)。如下图所示: 

 

  刚才说过了,架构师必须凭借他对于未来性的洞悉力和技能,来决定应该如何预留弹性空间。架构师将其所洞悉而得的,简明表达于下<框架需求时间图>里。例如,当架构师洞悉到该替业主预留「调整奖项」的空间时,就会画出需求图,如下图所示: 

 

  对于奖项金额,不同业主可能有不同的调整方法或不一样的计算公式。也可能同一位业主,但不同赌场需要不同的奖项调整公式。此时,这些不一样的公式就应该撰写在AP子类别里。而且,框架就必须将云服务所传来的奖项金额,传递给AP子类别,依据调整公式计算之后,在回传给框架基类别。这时必须修改IGame接口,增添一个函数(如prizeNotify()函数)。如下图所示: 

 

  Game云服务先把奖项传给GameEngine,此时GameEngine还不会立即把奖项显示于UI上;而是呼叫IGame接口的prizeNotify()而传递给myGaming。