2017-07-29 34 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()的调用都表现得非常好,(你知道,反射速度有点慢),但是如果你正在使用它进行测试,它应该没有关系。