2017-07-29 100 views
1
時減少重複代碼

[TL; DR] 的問題是,在AWrapperAType我不得不重複幾乎全部功能,其中總有語法:如何使用不兼容的封裝

public [TYPE/void] METHOD([OPT: args]) throws TestFailedException { 
[OPT: TYPE result = null;] 
long startTime = System.currentTimeMillis(); 
while (true) { 
    try { 
    beforeOperation(); 
    [OPT: result =] ((WrappedType) element).METHOD([OPT: args]); 
    handleSuccess(); 
    break; 
    } catch (Exception e) { 
    handleSoftFailure(e); 
    if (System.currentTimeMillis() - startTime > TIMEOUT) { 
     handleFailure(e); 
     break; 
    } else { 
     try { 
     Thread.sleep(WAIT_FOR_NEXT_TRY); 
     } catch (InterruptedException ex) { 
     } 
    } 
    } 
} 
[OPT: return result;] 
} 

可以說我有2班我不擁有:

public class IDontOwnThisType { 

    public void doA(String string) { System.out.println("doA"); } 
    public String doB(); {System.out.println("doB"); return "doB";} 
    public OtherTypeIDoNotOwn doC() {System.out.println("doC"); return new OtherTypeIDoNotOwn();} 

} 

public OtherTypeIDoNotOwn { 

    public void doD() { System.out.println("doD"); } 
    public String doE() { System.out.println("doE); } 
    public OtherTypeIDoNotOwn doF(String string) {System.out.println("doF"); return new OtherTypeIDoNotOwn();} 

} 

所以,我有一個接口:

public interface OperationManipulator { 

    void beforeOperation(); //called before operation 
    void handleSuccess(); //called after success 
    void handleSoftFailure(Exception e); //called after every failure in every try 
    void handleFailure(Exception e) throws TestFailedException; //called after reaching time limit 

} 

然後界面上方的一個延伸, 「模仿」 外部類的方法,但拋出自定義異常:

public interface IWrapper<T extends IType> extends OperationManipulator { 

    public void doA(String string) throws TestFailedException; 
    public String doB() throws TestFailedException;  
    public T doC() throws TestFailedException; 

} 

然後我們有IType,這也延伸:

public interface IType<T extends IType> extends OperationManipulator { 

    public void doD() throws TestFailedException; 
    public String doE() throws TestFailedException;  
    public T doF(String string) throws TestFailedException; 

} 

然後,我們有以上接口的抽象實現:

public abstract class AType<T extends IType> implements IType{ 

    Object element; // I do not own type of this object, cant modify it. 
    Class typeClass; 
    long TIMEOUT = 5000; 
    long WAIT_FOR_NEXT_TRY = 100; 

    public AType(Object element) { 
    this.element = element; 
    elementClass = this.getClass(); 
    } 

/* ... */ 

} 

然後,我們重寫函數期從所述接口,不含OperationManipulator接口:

函數不返回任何版本:

@Override 
public void doD() throws TestFailedException { 
    long startTime = System.currentTimeMillis(); 
    while (true) { 
    try { 
     beforeOperation(); 
     ((OtherTypeIDoNotOwn) element).doD(); 
     handleSuccess(); 
     break; 
    } catch (Exception e) { 
     handleSoftFailure(e); 
     if (System.currentTimeMillis() - startTime > TIMEOUT) { 
     handleFailure(e); 
     break; 
     } else { 
     try { 
      Thread.sleep(WAIT_FOR_NEXT_TRY); 
     } catch (InterruptedException ex) { 
     } 
     } 
    } 
    } 

函數返回正常參考版本:

@Override 
public String doE() throws TestFailedException { 
    String result = null; 
    long startTime = System.currentTimeMillis(); 
    while (true) { 
    try { 
     beforeOperation(); 
     result = ((OtherTypeIDoNotOwn) element).doE(); 
     handleSuccess(); 
     break; 
    } catch (Exception e) { 
     handleSoftFailure(e); 
     if (System.currentTimeMillis() - startTime > TIMEOUT) { 
     handleFailure(e); 
     break; 
     } else { 
     try { 
      Thread.sleep(WAIT_FOR_NEXT_TRY); 
     } catch (InterruptedException ex) { 
     } 
     } 
    } 
    } 
    return result; 
} 

和功能返回類型參數的對象:

@Override 
public T doF(String string) throws TestFailedException { 
    T result = null; 
    long startTime = System.currentTimeMillis(); 
    while (true) { 
    try { 
     beforeOperation(); 
     OtherTypeIDoNotOwn temp = ((OtherTypeIDoNotOwn) element).doF(string); 
     result = (T) elementClass.getDeclaredConstructor(Object.class).newInstance(temp); 
     handleSuccess(); 
     break; 
    } catch (Exception e) { 
     handleSoftFailure(e); 
     if (System.currentTimeMillis() - startTime > TIMEOUT) { 
     handleFailure(e); 
     break; 
     } else { 
     try { 
      Thread.sleep(WAIT_FOR_NEXT_TRY); 
     } catch (InterruptedException ex) { 
     } 
     } 
    } 
    } 
    return result; 
} 

AWrapper也是如此,但是th Ë區別是:

  1. 構造具有存儲型的類參數
  2. 對象被轉換爲IDoNotOwnThisType代替OtherTypeIDoNotOwn。此對象的功能也可能返回OtherTypeIDoNotOwn

IDoNotOwnThisTypeAWrapper包裝的類型。

OtherTypeIDoNotOwnAType包裝的類型。

然後,我們必須實現這些抽象類:

public class AssertingType extends AType<AssertingType> { 

    public AssertingType(Object element) { 
    super(element); 
    } 

    @Override 
    public void beforeOperation() { 
    //System.out.println("Asserting type before operation!"); 
    } 

    @Override 
    public void handleSuccess() { 
    //TODO: add to log file and log to output 
    System.out.println("Asserting type success!"); 
    } 

    @Override 
    public void handleFailure(Exception e) throws TestFailedException { 
    //TODO: add to log file, log to output and throw exception 
    System.out.println("Asserting type failure!"); 
    e.printStackTrace(); 
    throw new TestFailedException(); 
    } 

    @Override 
    public void handleSoftFailure(Exception e) { 
    //TODO: add to log file, log to output 
    System.out.println("Asserting type soft failure!"); 
    e.printStackTrace(); 
    } 

} 

和:

public class AssertingWrapper extends AWrapper<AssertingType> { 

    public AssertingWrapper (Object driver) { 
    super(driver, AssertingType.class); 
    } 

    @Override 
    public void beforeOperation() { 
    //TODO 
    System.out.println("Asserting wrapper success!"); 
    } 

    @Override 
    public void handleSuccess() { 
    //TODO: add to log file and log to output 
    System.out.println("Asserting wrapper success!"); 
    } 

    @Override 
    public void handleFailure(Exception e) throws TestFailedException { 
    //TODO: add to log file, log to output and throw exception 
    System.out.println("Asserting wrapper failure!"); 
    throw new TestFailedException(); 
    } 

    @Override 
    public void handleSoftFailure(Exception e) { 
    //TODO: add to log file, log to output 
    System.out.println("Asserting wrapper soft failure!"); 
    e.printStackTrace(); 
    } 
} 

因此,我們可以使用它像:

AssertingWrapper wrapper = new AssertingWrapper(new IDoNotOwnThisType()); 

AssertingType type = wrapper.doC(); 

AssertingType type2 = type.doF(); 

輸出:

Asserting wrapper before operation! 
doC 
Asserting wrapper success! 
Asserting type before operation! 
doF 
Asserting type success! 

完整的工作代碼是在這裏: LIVE

的問題是,我一直寫whiletrycatch等在ATypeAWrapper,可我莫名其妙地減少代碼的重複?在這個例子中,我爲每個類提供了3個函數,但在我的真實代碼中,我有50多個方法。我可以以某種方式包裝這些功能,以便重複的部分不重複?

+0

你能否給我們一個TL; DR這一切? –

+0

@MikeNakis提供 – xinaiz

+0

所以,我的解決方案是否適合你? –

回答

1

你的問題看起來相當複雜,我不能說自己已經能夠成功地將自己的思想包圍它,但我會試一試,因爲它似乎是一個非常有趣的問題,因爲我碰巧在處理你的情況類似的情況下有一定的經驗。

請原諒,如果我的答案由於我的誤解而變得完全不符合標準。

因此,您所尋找的是一種通用的解決方案,用於在調用前後注入自己的代碼,其中調用可以是任何方法,接受任意數量的參數,並返回任何類型的返回值。

在java中存在一個動態代理工具,您可以在java.lang.reflect.Proxy下找到它。

有了它,你可以做到以下幾點:

ClassLoader classLoader = myInterfaceClass.getClassLoader(); 
T temp = (T)Proxy.newProxyInstance(classLoader, new Class<?>[] { myInterfaceClass }, 
    invocationHandler); 

invocationHandler由您提供的,它是下列形式:

private final InvocationHandler invocationHandler = new InvocationHandler() 
{ 
    @Override 
    public Object invoke(Object proxy, Method method, Object[] arguments) 
     throws Throwable 
    { 
     /* your pre-invocation code goes here */ 
     /* ... */ 

     /* invoke original object */ 
     Object result = method.invoke(myObject, arguments); 

     /* your post-invocation code goes here */ 
     /* ... */ 

     /* return the result (will probably be null if method was void) */ 
     return result; 
    } 
}; 

所以,我想你也許能用最少的代碼解決您的問題。

動態代理的創建和method.invoke()的調用都表現得非常好,(你知道,反射速度有點慢),但是如果你正在使用它進行測試,它應該沒有關係。