目录
一 装饰模式案例说明
1.1 说明
1.2 代码
1.2.1 定义数据服务接口
1.2.2 定义基础数据库服务实现
1.2.3 日志装饰器
1.2.4 缓存装饰器
1.2.5 主程序调用
1.3 装饰模式的特点
一 装饰模式案例说明
1.1 说明
本案例是:数据查询增加缓存,使用到了装饰模式
1.装饰器链构建:
new CachingDecorator(new LoggingDecorator(new DatabaseService()))
2.顺序是:缓存装饰器包裹日志装饰器,日志装饰器包裹基础数据库服务
3.流程
-
第一次查询 (
user_123
):-
进入缓存装饰器:缓存中没有,继续向下
-
进入日志装饰器:记录开始日志
-
进入数据库服务:执行实际查询
-
返回日志装饰器:记录完成日志
-
返回缓存装饰器:缓存结果
-
最终返回结果给主程序
-
-
第二次查询 (
user_123
):-
缓存装饰器发现缓存中存在,直接返回
-
不会触发日志和数据库查询
-
1.2 代码
1.2.1 定义数据服务接口
public interface DataService {String fetchData(String userId);
}
1.2.2 定义基础数据库服务实现
public class DatabaseService implements DataService {@Overridepublic String fetchData(String userId) {// Simulate fetching data from a databasereturn "db中数据00: " + userId;}
}
1.2.3 日志装饰器
public class LoggingDecorator implements DataService {private final DataService wrappedService;public LoggingDecorator(DataService wrappedService) {this.wrappedService = wrappedService;}@Overridepublic String fetchData(String userId) {System.out.println("查询db中内容: " + userId);String result = wrappedService.fetchData(userId);System.out.println("logging查询db: " + result);return result;}
}
1.2.4 缓存装饰器
public class CachingDecorator implements DataService {private final DataService wrappedService;private final Map<String, String> cache = new HashMap<>();public CachingDecorator(DataService wrappedService) {this.wrappedService = wrappedService;}@Overridepublic String fetchData(String userId) {if (cache.containsKey(userId)) {System.out.println("查询缓存获取内容: " + userId);return cache.get(userId);} else {String result = wrappedService.fetchData(userId);cache.put(userId, result);return result;}}
}
1.2.5 主程序调用
public class TestZs {public static void main(String[] args) {DataService service = new CachingDecorator(new LoggingDecorator(new DatabaseService()));String result = service.fetchData("user_123");System.out.println("main方法显示结果:"+result);System.out.println("====================");// Fetching again to demonstrate cachingresult = service.fetchData("user_123");System.out.println(result);}
}
结果:
1.3 装饰模式的特点
关键点说明
装饰器顺序很重要:
如果把缓存装饰器放在最内层,日志每次都会记录
当前顺序确保了缓存命中时不会产生日志
线程安全:
使用 ConcurrentHashMap 保证缓存操作的线程安全
扩展性:
可以轻松添加其他装饰器(如性能监控、权限检查等)
透明性:
客户端代码不需要知道具体实现细节
这种设计模式非常适合需要动态添加功能的场景,同时保持了代码的整洁和可维护性