簡體   English   中英

匹配類型層次結構

[英]Matching against type hierarchy

假設我們有一個固定的類型層次結構,例如如下所示。 它是一個定義良好的樹,每個節點都有一個父節點(根節點除外)。

人類分類學

每種類型都有一個與之關聯的動作,應該在成功匹配時執行。 並不意味着一個動作對應於該類型的方法。 這只是任意關聯。

什么是將對象與類型層次結構匹配的智能方法? 應將每個對象與可能的最具體類型進行匹配。 對象已經創建。

從根目錄使用遞歸搜索。

一旦在兒童中找不到匹配項,請記住匹配的對象,如果其級別比上一次匹配更深。

偽代碼:

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

樹層次結構已經由類的聲明隱式定義。 您只需要通過鏈接的getSuperclass()調用遍歷一個樹分支到您要查找的類型。 然后可以使用簡單的哈希映射來組織樹節點(類類型)。

鑒於類型層次結構是靜態的,您可以將其定義為枚舉

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

然后將類類型映射到操作:

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]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM