重构if语句,我必须在其中初始化其他对象

时间:2018-11-23 18:41:58

标签: java if-statement hashmap

我正在寻找处理此方法的最聪明的方法

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    if (type.name().equals("CHECKINGACCOUNT")) {
        CheckingAccount cc = new CheckingAccount(cf, iban, 0);
        bankAccounts.put(iban, cc);
        return true;
    }
    if (type.name().equals("DEPOSIT")) {
        DepositAccount cd = new DepositAccount(cf, iban, 0);
        bankAccounts.put(iban, cd);
        return true;
    }
    if (type.name().equals("WEB")) {
        WebAccount cw = new WebAccount(cf, iban, 0);
        bankAccounts.put(iban, cw);
        return true;
    }
  return false;
}

AccountType是包含(DEPOSIT,WEB,CHECKINGACCOUNT)的枚举; bankAccounts是一个HashMap,其中包含iban(键)和CheckingAccounts OR DepositAccount OR WebAccountCheckingAccountsDepositAccountWebAccount是3个类,它们继承了称为Account的抽象类。

我正在尝试用HashMap替换if,该HashMap由用户使用String插入检查密钥(帐户类型),并实例化与HashMap中的密钥相关联的三个类之一。 问题是我无法在String和Account之间创建对应关系,因为我需要实例化该实例(但那一刻我不知道cf)

有人可以告诉我一些更好的方法来管理它吗?

3 个答案:

答案 0 :(得分:1)

为什么不使用工厂模式在枚举本身中为哪个帐户创建逻辑呢?从Java 8开始,这种模式就非常出色,因为您可以从字面上传入构造函数作为工厂的实现:

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    Account account = type.createAccount(cf, iban, 0);    
    bankAccounts.put(iban, account);
    return true;
}

public enum AccountType {
    CHECKING(CheckingAccount::new),
    DEPOSIT(DepositAccount::new),
    WEB(WebAccount::new);

    private final AccountFactory factory;
    AccountType(AccountFactory factory) {
        this.factory = factory;
    }

    public Account createAccount(String cf, String iban, int x) {
        return factory.create(cf, iban, x);
    }
}

public interface AccountFactory {
    Account create(String cf, String iban, int x);
}

与切换或映射方法相比,此解决方案具有巨大的优势:如果您添加了新的子类和新的帐户类型,则无法忘记处理此新类型。其他解决方案将在运行时(而不是编译时)失败或给出不正确的结果

答案 1 :(得分:0)

我建议不要使用任何类型的类型映射,因为它只会增加复杂性和运行时成本。 switch语句似乎是最简单的。 这是一个示例:

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    Account account;
    switch(type) {
      case CHECKINGACCOUNT:
        account = new CheckingAccount(cf, iban, 0);
        break;
      case DEPOSIT:
        account = new DepositAccount(cf, iban, 0);
        break;
      case WEB:
        account = new WebAccount(cf, iban, 0);
        break;
      default:
         return false; 
   } 
   bankAccounts.put(iban, account);
   return true;
}

但是,如果确定要使用类型映射:

static Map<AccountType, Class> TYPE_MAP = new HashMap<>() 
{
   {AccountType.CHECKINGACCOUNT, CheckingAccount.class},
   {AccountType.DEPOSIT, DepositAccount.class},
   {AccountType.WEB, WebAccount.class}
};

public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;
    if (!TYPE_MAP.containsKey(type)) return false;
    Class classType = TYPE_MAP.get(type);
    Account account = (Account)classType
      .getDeclaredConstructor(
        String.class,
        String.class,
        Integer.class)
      .newInstance(cf, iban, 0);
    bankAccounts.put(iban, account);
    return true;
}

答案 2 :(得分:0)

我的观点是,从概念上讲,此方法一切正常。我会稍作更改:

   public boolean addAccount(String cf, AccountType type) {
    String iban = name + cf;
    if (bankAccounts.containsKey(iban)) return false;

    Account ac;
    if (type == CHECKING) {
        ac = new CheckingAccount(cf, iban, 0);
    } else if (type == DEPOSIT) {
        ac = new DepositAccount(cf, iban, 0);
    } else if (type == WEB) {
        ac = new WebAccount(cf, iban, 0);
    }
    bankAccounts.put(iban, cc);
    return true;
}

我看不出有任何理由使用反射或工厂来创建acount实例使其变得更加复杂。它不会给您带来任何好处,您只会获得更多的代码,而新用户将花费更多的时间来理解它。