英文:
Template method pattern with arbitrary exception throwing
问题
假设我有一个抽象类 Base
,其中有一个具体方法 execute
和三个抽象方法 stepOne
、stepTwo
和 stepThree
...
public abstract class Base {
protected abstract void stepOne();
protected abstract void stepTwo();
protected abstract void stepThree();
public final void execute() {
// 做一些事情
stepOne();
// 做一些事情
stepTwo();
// 做一些事情
stepThree();
// 做一些事情
}
}
...并且有一个具体类 Sub1
继承自该抽象类:
public class Sub1 extends Base {
protected void stepOne() {
//...
}
protected void stepTwo() {
//...
}
protected void stepThree() {
//...
}
}
现在假设我有一个第二个子类 Sub2
,在 stepOne
和 stepTwo
方法中可能会抛出已检查异常:
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) {
// 处理 e1
} catch (Exception2 e2) {
// 处理 e2
}
Sub2 s2 = new Sub2();
s2.execute();
显然,这并不起作用,因为 Base
类中的方法没有声明任何异常。
如何在实现类中任意地抛出异常呢?
有没有一种方法,不必在 execute
方法中声明 throws Exception
,也不必始终使用 try-catch 块?
我还想避免将 execute
中的公共逻辑重复放入其子类中。
在这种情况下,有什么最佳解决方案?是否有更好的设计模式?
英文:
Let's say I have an abstract class Base
that has a concrete method execute
and three abstract methods stepOne
, stepTwo
and stepThree
...
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
}
}
...and is subclassed by a concrete class Sub1
public class Sub1 extends Base {
protected void stepOne() {
//...
}
protected void stepTwo() {
//...
}
protected void stepThree() {
//...
}
}
Now let's suppose I have a second subclass Sub2
that can throw a checked exception in stepOne
and stepTwo
public class Sub2 extends Base {
protected void stepOne() throws Exception1 {
//...
}
protected void stepTwo() throws Exception2 {
//...
}
protected void stepThree() {
//...
}
}
I would like to use these classes as follows:
Sub1 s1 = new Sub1();
try {
s1.execute();
} catch (Exception1 e1) {
//handle e1
} catch (Exception2 e2) {
//handle e2
}
Sub2 s2 = new Sub2();
s2.execute();
Clearly this doesn't work since the methods in Base
aren't declared with any exceptions.
How can I have arbitrary exception throwing in the implementing classes?
Is there a way without having to declare execute
with throws Exception
and always having to use a try-catch for it?
I'd also like to avoid duplicating the common logic in execute
into its subclasses.
What's the best solution here? Is there a better design pattern for this?
答案1
得分: 0
这是如何通过使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 {
// 执行一些操作
stepOne();
// 执行一些操作
stepTwo();
// 执行一些操作
stepThree();
// 执行一些操作
}
}
您可以通过扩展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) {
// 处理 e1
} catch (Exception2 e2) {
// 处理 e2
}
Sub1 s1 = new Sub1();
s1.execute();
注意:代码部分不需要翻译,已经包含在您提供的原始文本中。
英文:
Here is how you can solve this problem by making Base
class methods throw generic exceptions:
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
}
}
You can create a subclass that doesn't throw any checked exceptions by extending Base<RuntimeException, RuntimeException, RuntimeException>
as follows:
public class Sub1 extends Base<RuntimeException, RuntimeException, RuntimeException> {
protected void stepOne() {
//...
}
protected void stepTwo() {
//...
}
protected void stepThree() {
//...
}
}
And here is how you can create a subclass that can throw a checked exception in some steps:
public class Sub2 extends Base<Exception1, Exception2, RuntimeException> {
protected void stepOne() throws Exception1 {
//...
}
protected void stepTwo() throws Exception2 {
//...
}
protected void stepThree() {
//...
}
}
You can use these classes as follows:
Sub2 s2 = new Sub2();
try {
s2.execute();
} catch (Exception1 e1) {
//handle e1
} catch (Exception2 e2) {
//handle e2
}
Sub1 s1 = new Sub1();
s1.execute();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论