mybatis框架之装饰模式
学习开源框架源码,除了储备点知识以便于与面试官互相忽略之外,我想最重要的还是去学习大神如何写代码,如何做到职责单一,如何做到可扩展等。。。
本篇,试着总结一下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框架之装饰模式的更多相关文章
- mybatis框架之动态代理
坦白讲,动态代理在日常工作中真没怎么用过,也少见别人用过,网上见过不少示例,但总觉与装饰模式差别不大,都是对功能的增强,什么前置后置,其实也就那么回事,至于面试中经常被问的mybatis框架mappe ...
- Mybatis框架的多对一关联关系(六)
一.一对多的关联映射 一对多关联查询多表数据 1接口 public interface IDeptDAO { //根据部门编号查询该部门单个查询 public Emp getEmpById(Integ ...
- Spring+SpringMvc+Mybatis框架集成搭建教程
一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...
- Mybatis框架中实现双向一对多关系映射
学习过Hibernate框架的伙伴们很容易就能简单的配置各种映射关系(Hibernate框架的映射关系在我的blogs中也有详细的讲解),但是在Mybatis框架中我们又如何去实现 一对多的关系映射呢 ...
- Hibernate框架与Mybatis框架的对比
学习了Hibernate和Mybatis,但是一直不太清楚他们两者的区别的联系,今天在网上翻了翻,就做了一下总结,希望对大家有帮助! 原文:http://blog.csdn.net/firejuly/ ...
- 初识Mybatis框架,实现增删改查等操作(动态拼接和动态修改)
此第一次接触Mybatis框架确实是有点不适应,特别是刚从Hibernate框架转转型过来,那么为什么要使用Mybatis框架,Mybatis框架和Hibernate框架又有什么异同呢? 这个问题在我 ...
- Spring+MyBatis框架中sql语句的书写,数据集的传递以及多表关联查询
在很多Java EE项目中,Spring+MyBatis框架经常被用到,项目搭建在这里不再赘述,现在要将的是如何在项目中书写,增删改查的语句,如何操作数据库,以及后台如何获取数据,如何进行关联查询,以 ...
- SSM框架-----------SpringMVC+Spring+Mybatis框架整合详细教程
1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One ...
- Spring3.0 与 MyBatis框架 整合小实例
本文将在Eclipse开发环境下,采用Spring MVC + Spring + MyBatis + Maven + Log4J 框架搭建一个Java web 项目. 1. 环境准备: 1.1 创建数 ...
随机推荐
- 屏幕分辨率测试工具(舍弃)---chrome开发者工具devTools(强烈建议系统学习)
2019-01-25 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:// ...
- 阿里云不支持stmp 的25端口,必须
第一种方法 到阿里云解封25端口 特别注意阿里云的<25端口使用服务协议>: 我/我公司承诺并保证TCP 25端口仅用来连接第三方的SMTP服务器,从第三方的SMTP服务器外发邮件. ...
- noi.ac #227 random
分析 我们发现实际只要计算a[i]>b[j]和a[i]<b[j]哪种多即可 代码 #include<bits/stdc++.h> using namespace std; ], ...
- yum python mysql
lrwxrwxrwx root root Jun : pyspark -> /etc/alternatives/pyspark lrwxrwxrwx root root Jul : python ...
- Flask框架视图多层装饰器问题
Flask中的app.route装饰器 我们知道,在flask框架中,我们的路由匹配就是通过有参装饰器来实现的,我们看一个简单的例子: from flask import Flask, render_ ...
- Centos7配置定时重启服务器
Crontab是一个很方便的在unix/linux系统上定时(循环)执行某个任务的程序. 用 service crond status 查看 crond服务状态,如果没有启动则 systemctl s ...
- kali 开启xdebug
1.安装xdebug 参考https://xdebug.org/docs/install 2.配置 # vi /etc/php/7.3/mods-available/xdebug.inizend_ex ...
- PHP 开启错误显示并设置错误报告级别
警告:生产环境永远都不要显示任何错误信息! 显示错误(display_errors)和错误报告(error_reporting)是两回事.PHP 脚本发生错误时,可以根据设置选择是否报告这个错误(记录 ...
- linux flock()
表头文件 #include<sys/file.h> 定义函数 int flock(int fd,int operation); 函数说明 flock()会依参数operation所指 ...
- [Codeforces 163D]Large Refrigerator (DFS+剪枝)
[Codeforces 163D]Large Refrigerator (DFS+剪枝) 题面 已知一个长方体的体积为V,三边长a,b,c均为正整数,求长方体的最小表面积S V以质因数分解的形式给出 ...