匹配类型层次结构
Matching against type hierarchy
假设我们有一个固定的类型层次结构,例如如下图所示。它是一棵定义明确的树,其中每个节点都有一个父节点(根节点除外)。
每种类型都有一个与之关联的动作,应该在成功匹配时执行。这确实 而不是 意味着一个动作对应于所述类型的一个方法。这只是任意联想。
根据类型层次结构匹配对象的智能方法有哪些?
每个对象都应该与最具体的类型相匹配。对象已创建。
从根开始使用递归搜索。
一旦在children中找不到匹配项,如果比上次匹配的层次更深,则记住匹配的对象。
伪代码:
class MatchContext {
public int level;
public Node result;
}
public boolean match(Node object, int level, MatchContext ctx) {
if (no match)
return false;
boolean found = false;
for (all children in object) {
if (match(child, level + 1, ctx))
found = true;
}
if (!found && level > ctx.level) {
ctx.level = level;
ctx.result = this;
}
return found;
}
像这样调用它:
MatchContext ctx;
if (match(root, 0, ctx))
myAction(ctx.result);
树层次结构已由 classes 的声明隐式定义。您只需要通过链式 getSuperclass()
调用您要查找的类型来遍历一个树枝。然后可以使用简单的哈希映射来组织树节点(class 类型)。
鉴于类型层次结构是静态的,您可以将其定义为枚举
public enum ClassType{
HOMINOIDEA(HOMINOIDEA.class),
HOMINIDAE(HOMINIDAE.class),
HOMININAE(HOMININAE.class),
//and so on
UNKNOWN(null);
private static final Map<Class<?>, ClassType> typesMap = new HashMap<>();
public final Class<?> type;
static{
for (ClassType classType : EnumSet.allOf(ClassType.class)){
if(classType.type != null){
typesMap.put(classType.type, classType);
}
}
}
private ClassType(Class<?> type){
this.type = type;
}
public static ClassType getClassTypeOf(Class<?> type){
for(Class<?> lookupType = type; lookupType != null; lookupType = lookupType.getSuperclass()){
ClassType classType = typesMap.get(lookupType);
if(classType != null){
return classType;
}
}
return UNKNOWN;
}
}
然后将 class 类型映射到操作:
public static void main(String[] args){
EnumMap<ClassType, Action> actionMap = new EnumMap<>(ClassType.class);
actionMap.put(ClassType.HOMININAE, new HomininaeAction());
Homininae h = new Homininae();
actionMap.get(ClassType.getClassTypeOf(h)); //action associated with homininaes
}
这是另一个在某些方面更动态的版本
public class ActionDispatcher {
private final Map<Class<?>, Consumer<?>> actionMap = new HashMap<>();
public <T> void registerAction(Class<T> type, Consumer<? super T> action){
actionMap.put(type, action);
}
@SuppressWarnings("unchecked")
public void dispatchActionFor(Object object){
Consumer<Object> action = ((Consumer<Object>)getActionFor(object.getClass()));
if(action != null){
action.accept(object);
}
}
private Consumer<?> getActionFor(Class<?> type){
for(Class<?> lookupType = type; lookupType != null; lookupType = lookupType.getSuperclass()){
Consumer<?> action = actionMap.get(lookupType);
if(action != null){
return action;
}
}
return null;
}
//demo
public static void main(String[] args){
ActionDispatcher dispatcher = new ActionDispatcher();
dispatcher.registerAction(Number.class, n -> System.out.println("number: " + n));
dispatcher.registerAction(Double.class, d -> System.out.println("double: " + d));
dispatcher.registerAction(String.class, s -> System.out.println("first char: " + s.charAt(0)));
dispatcher.registerAction(Object.class, o -> System.out.println("object: " + o));
dispatcher.dispatchActionFor(new Integer(3));
dispatcher.dispatchActionFor(new Double(3.0));
dispatcher.dispatchActionFor("string");
dispatcher.dispatchActionFor(new Thread());
}
}
这个输出是:
number: 3
double: 3.0
first char: s
object: Thread[Thread-0,5,main]
假设我们有一个固定的类型层次结构,例如如下图所示。它是一棵定义明确的树,其中每个节点都有一个父节点(根节点除外)。
每种类型都有一个与之关联的动作,应该在成功匹配时执行。这确实 而不是 意味着一个动作对应于所述类型的一个方法。这只是任意联想。
根据类型层次结构匹配对象的智能方法有哪些? 每个对象都应该与最具体的类型相匹配。对象已创建。
从根开始使用递归搜索。
一旦在children中找不到匹配项,如果比上次匹配的层次更深,则记住匹配的对象。
伪代码:
class MatchContext {
public int level;
public Node result;
}
public boolean match(Node object, int level, MatchContext ctx) {
if (no match)
return false;
boolean found = false;
for (all children in object) {
if (match(child, level + 1, ctx))
found = true;
}
if (!found && level > ctx.level) {
ctx.level = level;
ctx.result = this;
}
return found;
}
像这样调用它:
MatchContext ctx;
if (match(root, 0, ctx))
myAction(ctx.result);
树层次结构已由 classes 的声明隐式定义。您只需要通过链式 getSuperclass()
调用您要查找的类型来遍历一个树枝。然后可以使用简单的哈希映射来组织树节点(class 类型)。
鉴于类型层次结构是静态的,您可以将其定义为枚举
public enum ClassType{
HOMINOIDEA(HOMINOIDEA.class),
HOMINIDAE(HOMINIDAE.class),
HOMININAE(HOMININAE.class),
//and so on
UNKNOWN(null);
private static final Map<Class<?>, ClassType> typesMap = new HashMap<>();
public final Class<?> type;
static{
for (ClassType classType : EnumSet.allOf(ClassType.class)){
if(classType.type != null){
typesMap.put(classType.type, classType);
}
}
}
private ClassType(Class<?> type){
this.type = type;
}
public static ClassType getClassTypeOf(Class<?> type){
for(Class<?> lookupType = type; lookupType != null; lookupType = lookupType.getSuperclass()){
ClassType classType = typesMap.get(lookupType);
if(classType != null){
return classType;
}
}
return UNKNOWN;
}
}
然后将 class 类型映射到操作:
public static void main(String[] args){
EnumMap<ClassType, Action> actionMap = new EnumMap<>(ClassType.class);
actionMap.put(ClassType.HOMININAE, new HomininaeAction());
Homininae h = new Homininae();
actionMap.get(ClassType.getClassTypeOf(h)); //action associated with homininaes
}
这是另一个在某些方面更动态的版本
public class ActionDispatcher {
private final Map<Class<?>, Consumer<?>> actionMap = new HashMap<>();
public <T> void registerAction(Class<T> type, Consumer<? super T> action){
actionMap.put(type, action);
}
@SuppressWarnings("unchecked")
public void dispatchActionFor(Object object){
Consumer<Object> action = ((Consumer<Object>)getActionFor(object.getClass()));
if(action != null){
action.accept(object);
}
}
private Consumer<?> getActionFor(Class<?> type){
for(Class<?> lookupType = type; lookupType != null; lookupType = lookupType.getSuperclass()){
Consumer<?> action = actionMap.get(lookupType);
if(action != null){
return action;
}
}
return null;
}
//demo
public static void main(String[] args){
ActionDispatcher dispatcher = new ActionDispatcher();
dispatcher.registerAction(Number.class, n -> System.out.println("number: " + n));
dispatcher.registerAction(Double.class, d -> System.out.println("double: " + d));
dispatcher.registerAction(String.class, s -> System.out.println("first char: " + s.charAt(0)));
dispatcher.registerAction(Object.class, o -> System.out.println("object: " + o));
dispatcher.dispatchActionFor(new Integer(3));
dispatcher.dispatchActionFor(new Double(3.0));
dispatcher.dispatchActionFor("string");
dispatcher.dispatchActionFor(new Thread());
}
}
这个输出是:
number: 3
double: 3.0
first char: s
object: Thread[Thread-0,5,main]