如何使用装饰器为文件文本读取类实现简单缓存机制?
使用装饰器模式实现Text接口的缓存优化
这问题问得恰到好处!装饰器模式天生就是用来做这种不修改原有类代码、动态增强功能的场景,完美契合开闭原则。咱们一步步来实现这个简单的缓存机制:
核心思路
装饰器模式的核心逻辑很清晰:
- 实现与被装饰对象完全相同的接口(这里就是
Text) - 内部持有一个被装饰的
Text实例作为委托对象 - 在目标方法中加入缓存判断逻辑,仅当缓存不存在时才调用委托对象的原方法
实现缓存装饰器
我们先写一个基础版的缓存装饰器CachedText,它会把读取到的文本内容缓存起来,后续调用直接返回缓存值:
import java.io.IOException; public final class CachedText implements Text { // 被装饰的原始Text实例(比如你的TextFromFile) private final Text delegate; // 缓存的文本内容,初始为null表示未缓存 private String cachedText; public CachedText(Text delegate) { this.delegate = delegate; } @Override public String asText() throws IOException { // 优先返回缓存:如果缓存已存在,直接返回 if (cachedText != null) { return cachedText; } // 缓存未命中时,调用原始方法读取内容并缓存 cachedText = delegate.asText(); return cachedText; } }
如何使用
使用时只需要把你的TextFromFile实例包装进CachedText即可,完全不需要改动原有类的代码:
public class Demo { public static void main(String[] args) throws IOException { // 创建原始的文件读取对象 Text rawFileText = new TextFromFile("data.txt"); // 用缓存装饰器包装它 Text cachedFileText = new CachedText(rawFileText); // 第一次调用:会实际读取文件并缓存内容 String firstResult = cachedFileText.asText(); // 第二次及以后调用:直接返回缓存,不会再读取文件 String secondResult = cachedFileText.asText(); } }
进阶优化(可选)
上面的基础版缓存是“静态”的,如果文件内容更新了,缓存不会自动刷新。如果需要处理这种场景,可以添加文件修改时间的检查,实现自动刷新缓存:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileTime; public final class AutoRefreshCachedText implements Text { private final Text delegate; private String cachedText; private FileTime lastFileModified; private final Path filePath; // 这里需要TextFromFile暴露路径,或者直接传入路径 public AutoRefreshCachedText(TextFromFile fileText) { this.delegate = fileText; this.filePath = Paths.get(fileText.path); // 可以给TextFromFile加一个getPath()方法替代直接访问字段 } @Override public String asText() throws IOException { FileTime currentModifiedTime = Files.getLastModifiedTime(filePath); // 如果缓存不存在,或者文件已修改,重新读取并更新缓存 if (cachedText == null || !currentModifiedTime.equals(lastFileModified)) { cachedText = delegate.asText(); lastFileModified = currentModifiedTime; } return cachedText; } }
这种方式既保留了原有类的核心功能,又通过装饰器灵活地添加了缓存能力,完全符合开闭原则!
内容的提问来源于stack exchange,提问作者Almas Abdrazak
相关产品推荐
相关产品推荐

