Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 根据类型层次结构进行匹配_Java_Design Patterns_Types_Casting_Hierarchy - Fatal编程技术网

Java 根据类型层次结构进行匹配

Java 根据类型层次结构进行匹配,java,design-patterns,types,casting,hierarchy,Java,Design Patterns,Types,Casting,Hierarchy,假设我们有一个固定的类型层次结构,如下图所示。它是一个定义良好的树,其中每个节点都有一个父节点(根节点除外) 每个类型都有一个与之关联的操作,该操作应在成功匹配后执行。这并不意味着动作对应于所述类型的方法。这只是随意的联想 根据类型层次结构匹配对象的智能方法有哪些? 每个对象都应该与可能的最特定类型相匹配。对象已创建。从根目录使用递归搜索 一旦在子对象中找不到匹配项,请记住匹配的对象(如果其级别比上一个匹配项更深) 伪代码: class MatchContext {

假设我们有一个固定的类型层次结构,如下图所示。它是一个定义良好的树,其中每个节点都有一个父节点(根节点除外)

每个类型都有一个与之关联的操作,该操作应在成功匹配后执行。这并不意味着动作对应于所述类型的方法。这只是随意的联想

根据类型层次结构匹配对象的智能方法有哪些?
每个对象都应该与可能的最特定类型相匹配。对象已创建。

从根目录使用递归搜索

一旦在子对象中找不到匹配项,请记住匹配的对象(如果其级别比上一个匹配项更深)

伪代码:

    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);

树层次结构已经由类的声明隐式定义。您只需要通过chained
getSuperclass()
调用要查找的类型来遍历一个树分支。然后,可以使用简单的哈希映射来组织树节点(类类型)

如果类型层次结构是静态的,可以将其定义为enum

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;
    }
}

我想到的解决方案是遍历类型和关联操作的元组树。是否要检查给定对象的类型?你能给我们举个代码示例吗?我不太明白。如果您有属于上述类/类型层次结构的对象,以及表示操作的方法,那么对这些对象调用这些方法将自动调用最具体的操作。我无法更改对象,因此无法利用多态性。我想用外部接口对外部对象进行分类。您可以控制对象的实例化吗?如果是这样,你可以使用适配器。我的直觉也是一棵树。这将产生O(logn)与max匹配。最后一个if条件中存在错误。为了在根级别上获得匹配,您需要将
ctx.level==0&&level==0
level
与逻辑or结合起来。还考虑了散列,但is有一个缺陷,您尝试在第二种方法中解决该缺陷。散列将丢失类型之间的层次关系。第二种方法还有一个次要的流程,因为它不区分类型(或接口)和实际类。一个类可以实现不同的接口,这将破坏树,因为节点的父节点将不再被很好地定义。@mike也在第一种方法中进行超类查找-在
getClassTypeOf()
中。我认为给定了一个定义良好的类型层次结构,您希望与这个给定的层次结构相匹配。给定的定义良好的树如何被“销毁”?但是,这两种方法都应该适用于在查找函数中使用
getInterfaces()
的接口。啊,对不起,我的错误。与类型相关:类型和类之间存在差异。或者用Java术语来描述接口和类。是的,您的解决方案可以工作,但是@RustyX的解决方案更稳定,因为它对实际的实现类是不变的。
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());
    }

}