1.什么是装饰模式?
不改变原有的代码实现增强。
Mybatis、Hibernate二级缓存都属于开发者自己去实现扩展的功能。
2.装饰模式的优缺点
优点:
1、装饰者是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。
2、通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。
3、装饰者完全遵守开闭原则。
缺点:
1、会出现更多的代码,更多的类,增加程序复杂性。
2、动态装饰时,多层装饰时会更复杂。
3.装饰模式的使用场景
多级缓存设计、mybatis中一级与二级缓存、IO流/发送短信
对接短信接口 阿里云—发送短信失败的情况下自动切换短信平台
阿里云—最开始基本功能
腾讯云----额外增强
华为云—额外增强
4.装饰模式定义
1、抽象组件:定义一个抽象接口,来规范准备附加功能的类
2、具体组件:将要被附加功能的类,实现抽象角色接口
3、抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口
4、具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。
5.装饰模式的架构图
6.案例(多级缓存)
6.1 创建查询缓存的接口
package com.xhs.pattern.decorate.service;
/**
* @desc:
* @projectName: pattern
* @author: xhs
* @date: 2022/6/17 10:13
* @version: JDK 1.8
*/
public interface ComponentCacheService {
/**
* 查询缓存中的数据
*
* @param key
* @param <T>
* @return
*/
<T> T getCache(String key);
}
6.2 创建查询一级缓存的实现类
package com.xhs.pattern.decorate.service.impl;
import com.xhs.pattern.decorate.service.ComponentCacheService;
import com.xhs.pattern.utils.JvmMapCacheUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @desc: 一级缓存JVM
* @projectName: pattern
* @author: xhs
* @date: 2022/6/17 10:14
* @version: JDK 1.8
*/
@Slf4j
@Service
public class JvmComponentCacheServiceImpl implements ComponentCacheService {
/**
* 查询缓存中的数据
*
* @param key
* @param <T>
* @return
*/
@Override
public <T> T getCache(String key) {
// 查询一级缓存 jvm缓存
String entity = JvmMapCacheUtils.getEntity(key, String.class);
log.info("---------------查询一级缓存---------------");
if (entity == null) {
return null;
}
return (T) entity;
}
}
6.3 创建抽象装饰类(扩展功能)
package com.xhs.pattern.decorate.service;
/**
* @desc: 抽象装饰类
* @projectName: pattern
* @author: xhs
* @date: 2022/6/17 10:26
* @version: JDK 1.8
*/
public interface AbstractDecorateService extends ComponentCacheService {
}
6.4 创建二级缓存实现类
package com.xhs.pattern.decorate.service.impl;
import com.xhs.pattern.decorate.service.AbstractDecorateService;
import com.xhs.pattern.utils.JvmMapCacheUtils;
import com.xhs.pattern.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @desc: 二级缓存redis
* @projectName: pattern
* @author: xhs
* @date: 2022/6/17 10:27
* @version: JDK 1.8
*/
@Slf4j
@Service
public class RedisDecorateServiceImpl extends JvmComponentCacheServiceImpl implements AbstractDecorateService {
@Override
public <T> T getCache(String key) {
// 先查询一级缓存
String cache = super.getCache(key);
if (cache != null) {
return (T) cache;
}
// 一级缓存中没有数据查询二级缓存
// 可以是redis,也可以是mysql
String string = RedisUtil.getString(key);
log.info("---------------查询二级缓存---------------");
if (string == null) {
return null;
}
// 写入一级缓存
JvmMapCacheUtils.putEntity(key, string);
return (T) string;
}
}
6.5 创建测试的controller进行验证
package com.xhs.pattern.decorate.controller;
import com.xhs.pattern.decorate.service.impl.RedisDecorateServiceImpl;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @desc:
* @projectName: pattern
* @author: xhs
* @date: 2022/6/17 10:48
* @version: JDK 1.8
*/
@RestController
public class DecorateController {
/**
* 这边注入最后一级缓存
*/
@Resource
private RedisDecorateServiceImpl redisDecorateService;
/**
* 登录接口
* 访问地址:localhost:1114/login
*
* @param key
* @return
*/
@PostMapping("/decorate")
public String decorate(String key) {
String cache = redisDecorateService.getCache(key);
return cache;
}
}
7.查询测试
7.1 第一次查询
7.2 第二次查询
controller层注入最后一级缓存
多级缓存继承上一级缓存的类实现抽象装饰类
参照蚂蚁课堂第十一期