具有任意异常抛出的模板方法模式



假设我有一个抽象类Base,它有一个具体方法execute和三个抽象方法stepOnestepTwostepThree。。。

public abstract class Base {
protected abstract void stepOne();
protected abstract void stepTwo();
protected abstract void stepThree();
public final void execute() {
//do stuff
stepOne();
//do stuff
stepTwo();
//do stuff
stepThree();
//do stuff
}
}

并且被具体类Sub1子类化

public class Sub1 extends Base {
protected void stepOne() {
//...
}
protected void stepTwo() {
//...
}
protected void stepThree() {
//...
}
}

现在让我们假设我有第二个子类Sub2,它可以在stepOnestepTwo中抛出检查异常

public class Sub2 extends Base {
protected void stepOne() throws Exception1 {
//...
}
protected void stepTwo() throws Exception2 {
//...
}
protected void stepThree() {
//...
}
}

我想使用这些类如下:

Sub1 s1 = new Sub1();
try {
s1.execute();
} catch (Exception1 e1) {
//handle e1
} catch (Exception2 e2) {
//handle e2
}
Sub2 s2 = new Sub2();
s2.execute();

很明显,这是不起作用的,因为Base中的方法没有声明任何异常。

如何在实现类中进行任意异常抛出?有没有一种方法不必用throws Exception声明execute,并且总是使用try-catch?我还希望避免将execute中的公共逻辑复制到它的子类中。这里的最佳解决方案是什么?有更好的设计模式吗?

以下是如何通过使Base类方法抛出泛型异常来解决此问题:

public abstract class Base<E1 extends Exception, E2 extends Exception, E3 extends Exception> {
protected abstract void stepOne() throws E1;
protected abstract void stepTwo() throws E2;
protected abstract void stepThree() throws E3;
public final void execute() throws E1, E2, E3 {
//do stuff
stepOne();
//do stuff
stepTwo();
//do stuff
stepThree();
//do stuff
}
}

您可以通过如下扩展Base<RuntimeException, RuntimeException, RuntimeException>来创建一个不抛出任何已检查异常的子类:

public class Sub1 extends Base<RuntimeException, RuntimeException, RuntimeException> {
protected void stepOne() {
//...
}
protected void stepTwo() {
//...
}
protected void stepThree() {
//...
}
}

以下是如何创建一个子类,该子类可以在某些步骤中抛出已检查的异常:

public class Sub2 extends Base<Exception1, Exception2, RuntimeException> {
protected void stepOne() throws Exception1 {
//...
}
protected void stepTwo() throws Exception2 {
//...
}
protected void stepThree() {
//...
}
}

您可以按如下方式使用这些类:

Sub2 s2 = new Sub2();
try {
s2.execute();
} catch (Exception1 e1) {
//handle e1
} catch (Exception2 e2) {
//handle e2
}
Sub1 s1 = new Sub1();
s1.execute();

最新更新