如果只委托代理并且什么都不做,那么什么是好的?

时间:2017-11-23 20:37:20

标签: java spring architecture aop software-design

此处的示例来自本书:Professional Java Development with the Spring Framework

在AOP章节中,我们以AccountManager实现为例:

public class AccountManagerImpl implements AccountManager {
    private MailSender mailSender;
    private SimpleMailMessage message;
    private AccountDao accountDao;

    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void setMessage(SimpleMailMessage message) {
        this.message = message;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    private void sendMail(Exception ex) {
        SimpleMailMessage msg = new SimpleMailMessage(this.message);
        msg.setText("Encountered exception " + ex.getMessage());
        this.mailSender.send(msg);
    }

    public Account getAccount(String accountId) throws AccountNotFoundException, DataAccessException {
        try {
            return this.accountDao.findAccount(accountId);
        } catch (AccountNotFoundException ex) {
            sendMail(ex);
            throw ex;
        } catch (DataAccessException ex) {
            sendMail(ex);
            throw ex;
        }
    }

    public void createAccount(Account account) throws DataAccessException, {
        try {
            if (isInvalid(account)) {
                throw new InvalidAccountException(account);
                this.accountDao.saveAccount(account);
            } catch(IOException ex){
                sendMail(ex);
                throw ex;
            } catch(DataAccessException ex){
                sendMail(ex);
                throw ex;
            }
        }
    }
}

然后解释了面向方面编程的所有优点,进行了一些配置以将sendMail(ex)移动到Aspect,我们最终得到:

public class AccountManagerImpl implements AccountManager {
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public Account getAccount(String accountId)
            throws AccountNotFoundException, DataAccessException {
        return this.accountDao.findAccount(accountId);
    }

    public void createAccount(Account account) throws DataAccessException {
        this.accountDao.saveAccount(account);
    }
}

引用书本身:

  

结果是一项重大改进。 AccountManager纯粹是   负责帐户管理,使代码更简单   更易于阅读和维护。异常通知机制是   干净地模块化,以便它可以单独维护   商业逻辑。例如,一位开发人员现在可以修改   异常通知策略,无需修改大数字   在传统方法中会受到影响的文件。

对我来说,看起来AccountManagerImpl实际上是以前的经理,而第二个例子只是一场灾难。

如实现的第二版所示,Manager类根本没有做,只是将所有内容委托给一个AccountDao

我的具体问题是:为什么要实施此版本(第2版)?我们也可以将Aspect应用于AccountDao,不是吗?

2 个答案:

答案 0 :(得分:3)

我同意在重构后管理器的核心功能看起来并不令人信服。但其原因可能只是作者没有花太多时间寻找更好的例子。

方面的要点是:提取可在不同类中找到的横切功能。换句话说:您发现一个或多个类花费代码执行的操作并不真正适合每个类的核心职责。然后,您将此“非核心功能”抽象为方面 - 允许您转向AOP工具。通过让工具将相应的代码移动到各个方面,您可以整理核心业务逻辑。

答案 1 :(得分:0)

如果Manager类是Façade,那么它旨在隐藏其成员交互的复杂性。在您的示例中,它有点过于简单,因此效益不明显。但是考虑到对DAO的调用不是那么直接(需要一些锅炉代码),那么复杂性被Manager类隐藏是好的。或者让我们说DAO需要与其他对象进行一些交互,然后管理器类也隐藏了这种复杂性。对于外部客户端来说,调用很简单。