大数据Scala编程.问题集(03)
by 高焕堂
高老师陪您成长...
Q-03: 如何从TemplateMethod设计模式理解trait的两项接口?
Answer:
Scala的trait就是接口类(Interface class),其意味着,它的结构是抽象类,但其扮演接口的角色。通常,可从有两个不同视角去看待trait机制:
l 第一个视角:将trait对应到Java的"Interface"机制。此时,将trait看成一个接口(主要是抽象函数)加上一些具象函数;或者说接口里的某些函数具有实现代码。这是一般具有Java经验的开发者所孰悉的视角。
l 第二个视角:将tarit对应到 TemplateMethod设计模式。此时,将trait看成一个接口类,其定义了两项接口。具象函数对应到 TemplateMethod模式的TemplateMethod函数,成为提供给Client的服务接口(Client interface,简称CI)。并且将抽象函数对应到PrimitiveOperation()函数,成为控制子类(Subclass)的扩充接口(Extends interface,简称<I>)。如下图所示:
(GoF的Design Patterns一书里的TemplateMethod模式)
为什么上述第二个视角会受到(架构)设计师的重视呢? 兹先从简单的Client/Server架构说起吧,如下图:
由于这个Client调用了多个不同的接口(如图里的IS-1、IS-2 ... IS-n等),不仅导致Client模块会变得很复杂,而且这些接口的变动都会导致Client模块的变动,会大幅提升Server模块(如Server-1、Server-2 ... Server-n等)的变动(更新或改版)的成本。所以这种架构是不好的。
Gamma等专家在Design Patterns一书里提出了Facade模式来化解上述的问题。如下图:
Facade模式将Server端的众多接口(如图里的IS-1、IS-2 ... IS-n等)封装起来,转而提供单一接口(如IF接口)给Client来使用。这个Facade模快就能落实为Scala的trait机制。如下图:
如果将这个trait模块取名为TFacade,可表示如下图:
看起来,这个TFacade模块已经化解了上述的问题了。但是,从(架构)设计师的角度来看,经常会问一个议题,就是:谁来设计或开发这个trait模块呢?如下图:
因为TFacade掌控了从Client到Server之间的数据流动接口(通道)。从架构设计和分工的的角度来看,谁负责设计(或开发)这个trait模块,谁就掌握了这个信息流动接口(通道)。
为了让你看出这tarit模块所掌握的接口,我们将它配成TemplateMethod模式,如下图:
TFacade里的具象函数,成为对Cleint的服务接口,如下图:
TFacade里的抽象函数,成为与子类对接的接口,如下图:
仔细看看这TFacade模块内部的具象和抽象函数。可以看出来这TFacade模块的设计者(或开发者),他设计(或定义)了两项接口:
l CI接口:由TFacade的具象函数所构成的接口。它由TFacade来实现,让Client来享用。
l <I>接口:由TFacade的抽象函数所构成的接口。它是由TFacade(的开发者)所定义,让它的子类来实现服务于Client;而抽象函数(以<I>表示)则用来控制(然后服务)子类。而子类则实践了这个<I>接口(里的抽象函数)。如下图:
这两个接口有其微妙而重要的差别:对TFacade模块而言,CI是被动的接口;而<I>则是主动的接口。CI是由TFacade来实现,让Client来主动调用,TFacade是被动的提供服务,所以称为TFacade的被动型接口。反之,对TFacade模块而言,<I>则是主动的接口;<I>是TFacade(的开发者)定义的,由其子类所实现,让TFacade来主动调用子类提供的服务,所以称为TFacade的主动型接口。
我(高焕堂)从上述的TempalteMethod和Facade等设计模式,更进一步的进行抽象化,而得出更抽象、更通用的的设计模式,特别称为"EIT造形",如下图:
这TFacade(即trait)模块里的具象函数里的代码,担任信息流动的逻辑控制部分,相当于汽车的引擎功能,所以称为<E>部分。这TFacade模块里的抽象函数,担任这<E>与子类的接口部分,子类相当于汽车的轮胎部分,所以称为<T>部分。<I>则是引擎与轮胎的接口部分。
这就是一个EIT造形的架构了。
关于这EIT造形的<E&I>(可落实为trait机制)的知识及其妙用技术,请您观看
请继续学习:高老師的相關視頻
相关文章:大数据Scala编程问题集(01)
相关文章:大数据Scala编程问题集(02)
~ End ~