学习开源框架源码,除了储备点知识以便于与面试官互相忽略之外,我想最重要的还是去学习大神如何写代码,如何做到职责单一,如何做到可扩展等。。。

本篇,试着总结一下mybatis在缓存模块使用到的装饰模式。

或许一说到装饰模式就会扯到装饰模式四种角色,但我觉得这些都是扯蛋,没必需照本宣科,我觉得myabtis框架也不是完全的装饰模式,或许可以说是变异版本。

其实,我觉得大多的设计模式无非就是面向接口编程与接口引用的组合罢了!

下面看看mybatis框架的cache模块是如何使用装饰模式的

1. 首先,定义了一个cache接口,具体的功能都在接口中说明了,主要是putObject 和getObject

public interface Cache {

  String getId();
void putObject(Object key, Object value);
Object getObject(Object key);
Object removeObject(Object key);
void clear();
int getSize();
default ReadWriteLock getReadWriteLock() {
return null;
} }

2. 然后,再看一下Cache的继承体系

清一色的java类,并没有啥抽象类或者接口,这就与教科书中的装饰模式有点区别了。。。。

3. 每一个Cache实现类都持有一个Cache引用

看下LoggingCache类的源代码

public class LoggingCache implements Cache {

  private final Log log;
private final Cache delegate;
protected int requests = 0;
protected int hits = 0; public LoggingCache(Cache delegate) {
this.delegate = delegate;
this.log = LogFactory.getLog(getId());
} @Override
public String getId() {
return delegate.getId();
} @Override
public int getSize() {
return delegate.getSize();
} @Override
public void putObject(Object key, Object object) {
delegate.putObject(key, object);
} @Override
public Object getObject(Object key) {
requests++;
final Object value = delegate.getObject(key);
if (value != null) {
hits++;
}
if (log.isDebugEnabled()) {
log.debug("Cache Hit Ratio [" + getId() + "]: " + getHitRatio());
}
return value;
} @Override
public Object removeObject(Object key) {
return delegate.removeObject(key);
} @Override
public void clear() {
delegate.clear();
} @Override
public int hashCode() {
return delegate.hashCode();
} @Override
public boolean equals(Object obj) {
return delegate.equals(obj);
} private double getHitRatio() {
return (double) hits / (double) requests;
} }
LoggingCache类的构造器传入了一个Cache实例delegate, 再看getObject方法

这么一看,貌似很符合装饰模式的精神内核,但是并没有照搬装饰模式的套路。而且,,,这似乎与责任链的套路也很像。。。。

假设LoggingCache的构造器入参是FifoCache, 而FifoCache的构造器入参又是RedsiCache, 那么在调用LoggingCache#getObject方法时就会形成一条链:

LoggingCache#getObject()-----------> FifoCache#getObject()--------------------> RedisCache#getObject() (这难道不能算责任链嘛,当然与真正的责任又有些差别),

而且这条调用链中,LoggingCache#getObject ()进行前、后功能增强,而FifoCache#getObject()-进行了前置功能增强, 当然RedisCache#getObject()仅是查询redis库。

mybatis框架就是这样操作的,这条调用链具体怎么组合,完全看Cache的Caller是如何去构造链节点的关系,使用得相当灵活,我觉得它相当于: 责任链+装饰。

而实现这种套路的技术就是Cache的所有实现类中都持有了一个Cache对象的引用。 注意是Cache对象,而非Cache的具体实现对象!

或许这就是面向接口编程吧!

在以后工作中,能用就尽可能用吧,切记!

mybatis框架之装饰模式的更多相关文章

  1. mybatis框架之动态代理

    坦白讲,动态代理在日常工作中真没怎么用过,也少见别人用过,网上见过不少示例,但总觉与装饰模式差别不大,都是对功能的增强,什么前置后置,其实也就那么回事,至于面试中经常被问的mybatis框架mappe ...

  2. Mybatis框架的多对一关联关系(六)

    一.一对多的关联映射 一对多关联查询多表数据 1接口 public interface IDeptDAO { //根据部门编号查询该部门单个查询 public Emp getEmpById(Integ ...

  3. Spring+SpringMvc+Mybatis框架集成搭建教程

    一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...

  4. Mybatis框架中实现双向一对多关系映射

    学习过Hibernate框架的伙伴们很容易就能简单的配置各种映射关系(Hibernate框架的映射关系在我的blogs中也有详细的讲解),但是在Mybatis框架中我们又如何去实现 一对多的关系映射呢 ...

  5. Hibernate框架与Mybatis框架的对比

    学习了Hibernate和Mybatis,但是一直不太清楚他们两者的区别的联系,今天在网上翻了翻,就做了一下总结,希望对大家有帮助! 原文:http://blog.csdn.net/firejuly/ ...

  6. 初识Mybatis框架,实现增删改查等操作(动态拼接和动态修改)

    此第一次接触Mybatis框架确实是有点不适应,特别是刚从Hibernate框架转转型过来,那么为什么要使用Mybatis框架,Mybatis框架和Hibernate框架又有什么异同呢? 这个问题在我 ...

  7. Spring+MyBatis框架中sql语句的书写,数据集的传递以及多表关联查询

    在很多Java EE项目中,Spring+MyBatis框架经常被用到,项目搭建在这里不再赘述,现在要将的是如何在项目中书写,增删改查的语句,如何操作数据库,以及后台如何获取数据,如何进行关联查询,以 ...

  8. SSM框架-----------SpringMVC+Spring+Mybatis框架整合详细教程

    1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One  ...

  9. Spring3.0 与 MyBatis框架 整合小实例

    本文将在Eclipse开发环境下,采用Spring MVC + Spring + MyBatis + Maven + Log4J 框架搭建一个Java web 项目. 1. 环境准备: 1.1 创建数 ...

随机推荐

  1. unity项目警告之 LF CRLF问题

    unity中创建的脚本,以LF结尾. Visual studio中创建的脚本,以 CRLF结尾. 当我们创建一个unity脚本后,再用VS打开编辑保存后,这个文件既有LF结尾符,也有CRLF结尾符. ...

  2. VS code 同步设置与插件

    准备工作:拥有一个github账户,电脑上需安装VSCode.实现同步的功能主要依赖于VSCode插件 "Settings Sync"第一步:安装同步插件Settings Sync ...

  3. poj2376Cleaning Shifts (贪心求解)

    描述 大表哥分配 N (1 <= N <= 25,000) 只中的一些奶牛在牛棚附近做些清洁. 他总是要让至少一只牛做清洁.他把一天分成T段(1 <= T <= 1,000,0 ...

  4. 求bit中1的个数有几种做法

    原文 求bit中1的个数有几种做法: - x & (x - 1) - Hamming weight的经典求法,基于树状累加:http://en.wikipedia.org/wiki/Hammi ...

  5. [Linux] 017 网络命令与挂载命令

    1. 网络命令:write 命令名称:write 命令所在路径:/usr/bin/write 执行权限:所有用户 语法:write [用户名] 功能描述:给用户发信息,以 Ctrl-d 保存结束 范例 ...

  6. [Linux] 009 链接命令

    链接命令:ln 命令名称:ln 命令英文原意:link 命令所在路径:/bin/ln 执行权限:所有用户 语法:ln -s [原文件] [目标文件] 功能描述:生成链接文件 范例: 创建文件 /etc ...

  7. 开发中遇到的相关linux问题

    一:java.sql.SQLException: Access denied for user 'root'@'10.150.152.200' (using password: YES) 1:用户名后 ...

  8. Using text search in Web page with Sikuli

    在網頁中如何使用Sikuli找特定字串呢? 原理: 我們可以使用 組合鍵 ctrl + 來放大網頁的比例,使得sikuli的OCR功能找的更清準 實作: for i in range(4): type ...

  9. P3826 [NOI2017]蔬菜

    传送门 注意每一单位蔬菜的变质时间是固定的,不随销售发生变化 固定的...... 就是每一个单位的蔬菜在哪一天变质是早就定好了的 发现从第一天推到最后一天很不好搞 考虑反过来,从最后一天推到第一天,这 ...

  10. P2944 [USACO09MAR]地震损失2Earthquake Damage 2(网络流)

    P2944 [USACO09MAR]地震损失2Earthquake Damage 2 $P$个点,$C$条双向边.求最少删去几个点使$N$个给定的点与点$1$分开. 显然的最小割. 将点$i$套路地拆 ...