我们能重构这些方法吗?

3

我的课程中有实现如下方法的类:

void methodOne() {
    try {
        getHelper().doActionOne();
    } catch ( Exception ex ) {
        throw new CustomException( ex );
    }
}

void methodTwo() {
    try {
        getHelper().doActionTwo();
    } catch ( Exception ex ) {
        throw new CustomException( ex );
    }
}

void methodThree() {
    try {
        getHelper().doActionThree();
    } catch ( Exception ex ) {
        throw new CustomException( ex );
    }
}


void methodFour;
void methodFive;
...

有没有更好的方法来做这个?这些代码让我感到不舒服。

编辑:抱歉示例不清楚。我正在使用Hibernate实现GenericDao类,真正的代码类似于这样:

class GenericDaoImpl<T, PK> {

    PK create( T object ) {
        try {
           getSession().save( object );
        } catch( Exception ex ) {
           throw new DataAccessLayerException( ex );// wrap any exception to my exception
        }
    }

   T read( PK id ) {
       try {
           getSession().get( T.class, id );
       } catch ( Exception ex ) {
           throw new DataAccessLayerException( ex );
       }

   }

  void update( T object );
  void delete( T object );

}

3
请问您能否解释一下这些方法被调用的情境? - Ammu
为什么这段代码让你感到不舒服?我并没有看出你的代码有什么特别的问题。 - Edwin Dalorzo
不清楚你想要实现什么,所以很难推荐更好的方法。为什么要捕获所有异常并用自定义异常包装它们?看起来你可能试图通过未检查的异常避免所有已检查的异常。 - WhiteFang34
您的代码对我来说看起来完全有效,我没有理由认为它应该进行重构。当然,可以提出一些想法,但我怀疑它是否能比那更简单。 - Edwin Dalorzo
因为实现的“步骤”在方法中有点重复,所以我想找到一种减少代码输入的方法。 - Genzer
3个回答

6

这只是一个基本的建议,但您可以将其重构为类似于“命令模式”的东西。该模式允许您将一些功能封装在实现单个方法的类中。该类可以被实例化并传递到另一个类中执行,执行器类不需要知道或关心它正在做什么,它只需要调用execute()方法即可。如果操作需要参数,则实现Command接口的类可以包括在构造函数中设置或通过标准属性设置器设置的字段/属性。

创建一个如下所示的接口(我的Java已有点生疏,因此可能不是100%有效的语法):

public interface Command
{
    public void execute();
}

public class ActionOne implements Command
{
    public void execute()
    {
        // do actionOne...
    }
}

public class ActionTwo implements Command
{
    public void execute()
    {
        // do actionTwo...
    }
}

// etc. for more actions

接下来创建执行操作的类,调用代码只需要传入正确的Command实现类即可。

public class Executor
{

    public void executeCommand(Command command)
    {
        try
        {
            // Put any boilerplate code here (logging, auditing, etc.)
            command.execute();
        }
        catch (Exception ex)
        {
            // Put general error handling code here.  If you're just catching and rethrowing, consider not catching the Exception at this level.  If it's a checked exception, add a throws clause to the method.
            throw new CustomException();
        }
    }
}

我感激您的建议,但是使用命令模式似乎会增加我的类的数量。我正在考虑使用类方法动态调用。 - Genzer
2
你为什么关心增加类的数量呢?10个小而专注的类比一个需要完成10个不同任务的大类更好。除非你绝对必须这样做,否则我也会避免使用反射。使用一些基本接口和类可以更简洁地表达您的代码。 - Andy White
我正在尝试重构一个存在类似问题的类。如果我的类有大约100个方法,还有什么进一步的建议吗?我唯一能想到的是为Action类创建一个新的包。 - TheAmpersand

1

是的,您可以随时重构代码。唯一的问题是您是否要重构以使其更好还是更糟。这段代码奇怪的迹象表明它可以做得更好。

这看起来像是多态的一个很好的候选项。尝试使用五个不同的类和一个共享方法代替五个不同的方法。接口将把它们全部联系在一起。

public interface DoIt {
  public void doIt();
}

public class One implements DoIt {
  public void doIt() {
    // code which was previously in getHelper.doActionOne();
  }
}

public class Two implements DoIt {
  public void doIt() {
    // code which was previously in getHelper.doActionTwo();
  }
}

...

public class Five implements DoIt {
  public void doIt() {
    // code which was previously in getHelper.doActionFive();
  }
}

现在唯一的事情是为这种情况创建正确的类,并调用其doIt()方法。

0

这个功能是由Spring Framework提供的,还有许多其他功能。首先,它有一个特定的HibernateTemplate,将每个Hibernate特定的异常映射到一个未经检查的、相关的Spring异常。其次,它提供了一个AOP服务,以在方法级别上转换异常,因此您可以指定映射一次并在多个服务中统一应用它们。

虽然我不会仅仅为了这个功能而使用Spring,但它对于构建应用程序有巨大的好处,我已经使用它很多年了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接