模板方法模式,带有任意异常抛出功能。

huangapple go评论68阅读模式
英文:

Template method pattern with arbitrary exception throwing

问题

假设我有一个抽象类 Base,其中有一个具体方法 execute 和三个抽象方法 stepOnestepTwostepThree...

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,在 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) {
    // 处理 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&lt;E1 extends Exception, E2 extends Exception, E3 extends Exception&gt; {
    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&lt;RuntimeException, RuntimeException, RuntimeException&gt; as follows:

public class Sub1 extends Base&lt;RuntimeException, RuntimeException, RuntimeException&gt; {
    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&lt;Exception1, Exception2, RuntimeException&gt; {
    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();

huangapple
  • 本文由 发表于 2020年9月13日 20:49:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/63870971.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定