原文地址:https://javatar.iteye.com/blog/706098
原文地址:https://javatar.iteye.com/blog/1041832
原文地址:https://javatar.iteye.com/blog/706098
这篇文章其实可以算是整体设计中的一环了,但是在读这几篇文章的时候,感受颇多。对于文章中的描述,个人有以下几点体会,仅供参考,有疑问一起留言讨论。
框架扩展原则
- 微核心+插件式
微核心设计,我们可以想一下linux系统。嵌入式linux的核心最小可以到几兆。通常情况下可以裁掉不必要的第三方驱动和服务。这里插架有点类似于各种驱动程序,插架实现预先定义好的借口功能。然后通过一定手段(比如说配置加载)进内存。微内核+插架,决定了这种设计模式必须要对第三方扩展友好,否则迟早玩完。那么究竟如何实现微核心+插架的框架的架构呢?
Eclipse的微核是OSGi, Spring的微核是BeanFactory,Maven的微核是Plexus。之前搞过一个网关系统,使用的是Wso2的api-gateway来做的,这个就是基于osgi来实现网关服务的动态插拔的。至于我们自己的业务系统可以使用Spring帮我们完成这个过程。至于剥离业务逻辑
- 一致性概念模型
这个呢,简单点说,就是保证一个内部实体设计的时候要逐层封装,而不能过于分散实体。提供统一完整的实体类。对于初期的童鞋来说,一个好办法就是,放在一个对象里。当然最好的方式就是逐层封装起来,层次清晰明朗。
分层,组合式扩展,而不是泛化式扩展。
在重要的过程上设置拦截接口
接口设计原则
框架或组件通常有两类客户,一个是使用者,一个是扩展者, API(Application Programming Interface)是给使用者用的,
而SPI(Service Provide Interface)是给扩展者用的, 在设计时,尽量把它们隔离开,而不要混在一起, 也就是说,使用者是看不到扩展者写的实现的。
比如:一个Web框架,它有一个API接口叫Action, 里面有个execute()方法,是给使用者用来写业务逻辑的, 然后,Web框架有一个SPI接口给扩展者控制输出方式, 比如用velocity模板输出还是用json输出等, 如果这个Web框架使用一个都继承Action的VelocityAction和一个JsonAction做为扩展方式, 要用velocity模板输出的就继承VelocityAction,要用json输出的就继承JsonAction, 这就是API和SPI没有分离的反面例子,SPI接口混在了API接口中, 合理的方式是,有一个单独的Renderer接口,有VelocityRenderer和JsonRenderer实现, Web框架将Action的输出转交给Renderer接口做渲染输出。
合理的方式是,有一个单独的 Renderer 接口,有 VelocityRenderer 和 JsonRenderer 实现,Web 框架将 Action 的输出转交给 Renderer 接口做渲染输出。
另外一个设计原则:接口功能职责单一
接口设计体现了编码的功底。很多时候,如果处理不好接口定义的边界问题,会使得边界臃肿累赘。比如说我~汗颜!虚极在文章中举了个例子:,远程调用框架它的协议是可以替换的, 如果只提供一个总的扩展接口,当然可以做到切换协议, 但协议支持是可以细分为底层通讯,序列化,动态代理方式等等, 如果将接口拆细,正交分解,会更便于扩展者复用已有逻辑,而只是替换某部分实现策略, 当然这个分解的粒度需要把握好。 这里说的粒度其实就是边界问题。而处理的边界,可以认为对其处理事务的分类。比如这里的底层通讯方式,序列化方式,动态代理方式,这三个完全可以是三个接口,然后组合在一起使用。而不是内部硬编码在一起。这样就失去了灵活性。
领域设计原则
虚极大神博客中写的非常清楚。领域分离设计,领域包含:实体域,会话域以及服务域。实体域存放的是不可变的元数据;会话域存放的是临时性的或者是状态数据,可以认为每个请求都会创建的一个自己私有的对象;服务域可以说是行为域就是操作前边两个的对象。我们熟知的spring中的applicationContext加载配置信息,管理Bean的生命周期。如何保证服务域的线程安全呢,我们可以使用单例模式。单例负责组装信息,并执行调用链。
这样设计,逻辑非常清晰,而且从目前来看,至少实体和会话域绝对线程安全,保证最少上锁实现。如果服务域能够设计的很好,支持无锁编程。