2014-10-02 54 views
1

這個問題被問了很多次,但我找不到優雅的解決方法。 這個例子可以作爲期望:方法的泛型重載 - 解決方法

public class RequestWrapper<T> { 
    private final T request; 
    private final Class<T> type; 

    public RequestWrapper(T request, Class<T> type) { 
     this.request = request; 
     this.type = type; 
    } 

    public T getRequest() { 
     return request; 
    } 

    public Class<T> getType() { 
     return type; 
    } 
} 

public class Service { 

    private void invoke(String request) { 
     System.out.println("String:" + request); 
    } 

    private void invoke(Object request) { 
     System.out.println("Object:" + request + "," + request.getClass().getSimpleName()); 
    } 

    public static void main(String[] args) { 
     RequestWrapper<String> sw = new RequestWrapper<String>("A", String.class); 
     RequestWrapper<Integer> iw = new RequestWrapper<Integer>(Integer.valueOf(0), Integer.class); 

     new Service().invoke(sw.getRequest()); 
     new Service().invoke(iw.getRequest()); 
    } 
} 

但我需要添加一個方法來服務類這之前做一些事情/ Invoke方法的調用之後:

public void invoke(RequestWrapper<?> wrapper) { 
    try { 
     // ... 
     invoke(wrapper.getType().cast(wrapper.getRequest())); 
     invoke(wrapper.getRequest()); 
    } catch(Exception e) { 
     // ... 
    } 
} 

則主要方法將包含:

new Service().invoke(sw); 

我明白使用invoke(Object request)而不是invoke(String request)的原因。 什麼是一個優雅的解決方案來調用正確的調用方法,並能夠在它之前/之後執行一些常見操作?

要有一個接口,例如Invoker,實現它StringInvoker,Invoker>和調用map.get(wrapper.getType())。invoke(wrapper.getRequest())是可能的解決方案,但我期望更好的東西。

回答

0

訪客模式可以解決它。唯一的缺點是沒有可能寫:

new Service().invoke(new RequestWrapper<String>("A")); 

我的實現:

public class Service { 
    public void invoke(RequestWrapper<?> wrapper) { 
     try { 
      // ... 
      wrapper.invoke(this); 
     } catch(Exception e) { 
      // ... 
     } 
    } 

    public void invoke(String request) { 
     System.out.println("String:" + request); 
    } 

    public void invoke(Boolean request) { 
     System.out.println("Boolean:" + request); 
    }  

    public static void main(String[] args) { 
     RequestWrapper<Boolean> rw = new BooleanRequestWrapper(Boolean.TRUE); 

     new Service().invoke(rw); 
    } 
} 

abstract class RequestWrapper<T> { 
    protected final T request; 

    public RequestWrapper(T request) { 
     this.request = request; 
    } 

    public abstract void invoke(Service v); 
} 

class BooleanRequestWrapper extends RequestWrapper<Boolean> { 

    public BooleanRequestWrapper(Boolean request) { 
     super(request); 
    } 

    public void invoke(Service service) { 
     service.invoke(request); 
    } 
} 
0

您可以檢查的類型和顯式轉換它,例如(我還加Integer所以你可以看到分支上的更多類型):

Class<?> c = wrapper.getType(); 

if (c == String.class) 
    invoke((String) wrapper.getRequest()); // Invokes invoke(String) 
else if (c == Integer.class) 
    invoke((Integer) wrapper.getRequest()); // Invokes invoke(Integer) 
else 
    invoke(wrapper.getRequest());   // Invokes invoke(Object) 

注:

如果你去在此路徑上,甚至不需要將請求類型存儲在RequestWrapper類中,因爲您可以輕鬆地使用請求本身的instanceof運算符來檢查其類型。如果您「擺脫」了請求類型,那麼您當前的RequestWrapper類將只包含請求,因此在這種情況下甚至不需要RequestWrapper

+0

沒錯,但是這正是我想要擺脫。如何利用方法重載的不同想法? – Samot 2014-10-02 13:02:26