面试题答案
一键面试技术点
- 缓存优化:使用缓存机制存储已经访问过的对象及计算结果,避免重复计算。例如,可以采用Guava Cache,它提供了易于使用的缓存功能。
- 异步处理:对于耗时的访问操作,引入异步处理机制。Java的CompletableFuture可以方便地实现异步任务的编排与处理。
- 动态代理:通过动态代理在运行时为对象生成代理类,在不改变原有类结构的情况下增强功能,比如添加日志记录、性能监控等。
设计思路
- 缓存设计:在访问者类中添加缓存结构,如
ConcurrentHashMap
。当访问对象时,先检查缓存中是否有对应的结果,如果有则直接返回,否则进行计算并将结果存入缓存。 - 异步设计:将访问操作封装成异步任务,使用线程池进行管理。在访问者的访问方法中,提交任务到线程池,并返回CompletableFuture对象,调用者可以通过该对象获取最终结果。
- 动态代理设计:使用Java的Proxy类或CGLIB库创建动态代理。在代理类中,除了调用实际的访问方法,还可以进行额外的操作,如记录访问时间、统计访问次数等。
代码框架搭建
- 缓存优化代码示例
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
class OptimizedVisitor implements Visitor {
private final Cache<Object, Object> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
@Override
public void visit(Element element) {
Object result = cache.getIfPresent(element);
if (result != null) {
// 直接返回缓存结果
System.out.println("Returning from cache: " + result);
return;
}
// 计算结果
result = performComplexCalculation(element);
cache.put(element, result);
System.out.println("Calculated and cached: " + result);
}
private Object performComplexCalculation(Element element) {
// 具体业务计算逻辑
return element.getData();
}
}
- 异步处理代码示例
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class AsyncVisitor implements Visitor {
private static final ExecutorService executor = Executors.newFixedThreadPool(10);
@Override
public CompletableFuture<Void> visit(Element element) {
return CompletableFuture.runAsync(() -> {
// 异步执行访问操作
performComplexCalculation(element);
}, executor);
}
private void performComplexCalculation(Element element) {
// 具体业务计算逻辑
System.out.println("Performing async calculation on " + element.getData());
}
}
- 动态代理代码示例(以Java Proxy为例)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class VisitorProxyFactory {
public static Visitor createProxy(Visitor visitor) {
return (Visitor) Proxy.newProxyInstance(
visitor.getClass().getClassLoader(),
visitor.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method invocation: " + method.getName());
long startTime = System.currentTimeMillis();
Object result = method.invoke(visitor, args);
long endTime = System.currentTimeMillis();
System.out.println("After method invocation. Time taken: " + (endTime - startTime) + " ms");
return result;
}
});
}
}
在实际项目中,可以根据具体需求灵活组合这些优化方式,以提高访问者模式的性能和扩展性。