假设我想使用使用匿名类的Command模式。在Invoker中我想应用缓存。像这样:
// command abstract class
public static abstract class ViewScopeCacheCommand<T> {
public abstract T invoke();
}
// innvoker
public static class ViewScopeCache<T> {
// cache
private Map<String,T> pageCache = null;
public ViewScopeCache() {
pageCache = new HashMap<String,T>();
}
// get from cache
public T get(String key) {
return pageCache.get(key);
}
// put to cache
public void put(String key, T t) {
pageCache.put(key, t);
}
// I want to say how to load the result of not in cache - given by command
public T getLazy(String key, ViewScopeCacheCommand<T> command) {
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
public void invalidate() {
pageCache.clear();
}
// I want to identify the cache by command
/*
public T getLazy(ViewScopeCacheCommand<T> command) {
String magicKey = .. derive from command
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
*/
}
假设我有两个使用它的位置:
..
Result getResult1() {
viewScopeCache.get("key1", new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLX }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get("key2", new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLY}}); // does not need to be SQL, can be a service B call
}
..
确定这项工作但我可以识别匿名的ViewScopeCacheCommand吗?这样用法会简化这个
..
Result getResult1() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLX }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call DB SQLY}}); // does not need to be SQL, can be a service B call
}
..
如果我已经完成了普通的类扩展,我可以使用instanceof,反射等。但是有一些机制来识别调用SQLX的command1和调用SQLY的命令2之间的区别 它可能是基于反射的,它可能是代码行..
我心中唯一的想法是注释:( ..但这很蹩脚..
问题是:我可以推断出在类级别上可能是唯一的Key来识别特定的命令..
我可以在Command {abstract String getUniqueKey(){}}中添加第二个方法并强制它被定义..但那很丑:)
答案 0 :(得分:1)
抽象类可以有匿名类可以调用的构造函数:
public static abstract class ViewScopeCacheCommand<T> {
private final String uniqueKey;
public ViewScopeCacheCommand(String uniqueKey) {
this.uniqueKey= uniqueKey;
}
public String getUniqueKey() {
return uniqueKey;
}
public abstract T invoke();
}
用法如下:
..
Result getResult1() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>("key1") {
..invoke(){ call DB SQLX }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>("key2") {
..invoke(){ call DB SQLY}}); // does not need to be SQL, can be a service B call
}
..
答案 1 :(得分:0)
匿名类在JVM级别上并不是真正的匿名。它仍然有一个与之关联的唯一Class实例。
他是正确的,内部(匿名)类在JVM级别上有唯一的标识符。
这是我的测试:
public class Demo {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
loop();
}
}
private static void loop() {
test(new TestMe() {
@Override
int getKey() {
return 100;
}
});
test(new TestMe() {
@Override
int getKey() {
return 200;
}
});
}
public abstract static class TestMe {
abstract int getKey();
}
public static void test(TestMe testMe) {
System.out.println(testMe.getClass() + " " + testMe.getKey());
}
}
输出
class Demo$1 100
class Demo$2 200
class Demo$1 100
class Demo$2 200
class Demo$1 100
class Demo$2 200
class Demo$1 100
class Demo$2 200
因此问题中的代码可以简化为
// command abstract class
public static abstract class ViewScopeCacheCommand<T> {
public abstract T invoke();
}
// innvoker
public static class ViewScopeCache<T> {
// cache
private Map<String,T> pageCache = null;
public ViewScopeCache() {
pageCache = new HashMap<String,T>();
}
// get from cache
public T get(String key) {
return pageCache.get(key);
}
// put to cache
public void put(String key, T t) {
pageCache.put(key, t);
}
/*
// I want to say how to load the result of not in cache - given by command
public T getLazy(String key, ViewScopeCacheCommand<T> command) {
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
*/
public void invalidate() {
pageCache.clear();
}
// I want to identify the cache by command
/*** solution ***/
public T getLazy(ViewScopeCacheCommand<T> command) {
String magicKey = command.getClass().toString(); // <--- solution
if(get(key) == null) {
T t = command.invoke();
pageCache.put(key, t);
}
return get(key);
}
}
使用惰性用例(将结果放入缓存并加载,如果缓存中不存在,则加载):
..
Result getResult1() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call anything X }}); // does not need to be SQL, can be a service A call
}
..
Result getResult2() {
viewScopeCache.get(new ViewScopeCacheCommand<Result>() {
..invoke(){ call anything Y}}); // does not need to be SQL, can be a service B call
}
..
我当然也可以覆盖我只需要密钥的情况:
Result getResult3() {
if(something empty) {
//fetch it
viewScopeCache.put("key3",..Z..);
}
viewScopeCache.get("key3");
}
..
感谢大家的讨论和解决。