Patterns Of Enterprise Application Architecture
1, 事务脚本 vs. 领域模型(Transaction Script vs. Domain Model)
作者基于功能的复杂性来区分两种模式的使用时机,却忽略了另外一个因素:功能的增加
领域模型将功能和数据置于同一个对象中,当需要增加新的功能时,只能通过为对象增加新的方法来实现,这造成了对象接口的不稳定,并无法在没有源代码的情况下进行功能增加
而事务脚本则可以灵活的进行功能的扩展:增加一个Command Handler子类,配置到系统中即可,不需要改变对象接口,不需要修改源代码
进一步,可以使用Visitor模式将领域模型和事务脚本粘合起来:核心或常用功能用领域模型建模,可以使用子类化消除复杂的逻辑判断,而预留一个accept(visitor)接口来支持功能的扩展
总之,当数据变化不大,而功能经常增加时(不是同一个功能逻辑复杂性增加,而是新功能的增加),事务脚本配合Command模式理论上拥有更好的扩展性
2,表模块(Table Module)
是“管理者(Manager)”模式的变种,管理的不是通用的内存对象,而是“实际的或虚拟的表,及其中的行”,可用于隐藏数据层,甚至根据表之间的关系,可以建立一个Table Module的继承层次
3,服务层(Service Layer)
初看到名字时,还以为基本是和“Enterprise.Solution.Patterns.Using.Microsoft.Dot.NET”中的“Service Interface”类似的模式,细看之下,发现正是最近想求证的一个模式,因为在自己的项目中混合使用了事务脚本和领域模型(前面1,事务脚本 vs. 领域模型中提到的问题和最终的方案,正是目前自己项目中的问题和方案),一直感觉不是很纯粹的设计,现在发现,目前的设计基本类似Service layer,只需要再明确划分一下“领域逻辑”和“应用逻辑”即可
4, 数据映射器(Data Mapper)
在解决只允许设置一次的属性问题时,作者除了使用标准的ctor设置外,还使用了基于状态的setter方法,这种setter在第一次被调用后,设置某个内部状态,后续的调用发生时,将抛出assertion error;最后作者说明了这种方法的缺陷:类中有个不允许大部分客户调用的方法,否则,基于反射的方法会绕过Java的保护机制,而这是不被推荐的
我也经常碰到这类问题,通常我是使用“friend interface”来解决这类问题,参见The Programming Language Idioms
5,继承映射器(Inheritance Mappers)
作者将find方法放在了具体映射器中,而不是抽象映射器,给出的原因是一般OO语言不允许改变虚函数的返回值类型,而放在抽象映射器中将不得不downcast;C++支持返回值协变,而Java从5.0开始也已经支持返回值协变,所以作者可以修改这一小节了,将find方法拉到映射器基类中;参见“抗变与协变[1]”,“抗变与协变[2]”
6,查询对象(Query Object)
基本上类似我们用的条件对象,参见http://blog.csdn.net/gongflow/archive/2004/12/11/212694.aspx
7,前端控制器(Front Controller)
Gateway的一种应用,除了Web程序外,还可以用在面向消息的系统中
8,控制器
页面控制器,前端控制器,应用控制器
9,分布模式
远程外观+服务层+服务桩+数据传输对象+控制反转,我们搭建了一个独立或嵌入式的引擎:它可以是独立运行的平台,通过Web服务和消息系统来响应外界请求;也可以是普通类库,嵌入到其它系统中去;改变配置文件中的一个配置项就可以切换两种模式,大大提高了回归测试和持续集成的速度和方便性
10,数据传输对象
作者对DTO序列化的阐述解释了.Net内置的自定义二进制序列化机制优于Java内置的自定义二进制序列化的地方:使用字典,增强了对象不同版本间的容错性,减少了序列化/反序列化的顺序依赖性;但不同版本间的容错性到底是减少了程序的错误,还是增加了潜在的危险?
11,服务器会话状态
作者对有状态会话bean和无状态会话bean之间的性能差别进行了测试,得出了有状态会话bean并不是在任何情况下都要比无状态会话bean效率低的结论,几百个并发的负载下二者差不多;这就意味着对于企业内部应用来说,性能不再是影响会话bean类型选择的因素;这基本类似Herb Sutter对“写时拷贝(COW,Copy On Write)”性能神话的颠覆
12,入口(Gateway)
我们的系统中至少对Xml和消息系统使用了gateway或者说wrapper facade,在将系统从.Net移植到J2EE时节省了大量时间
上一篇: mybatis-plus:自动填充功能
下一篇: TypeScript Usage