Java 重构if语句,其中我必须初始化不同的对象
我正在寻找处理这种方法的最聪明的方法Java 重构if语句,其中我必须初始化不同的对象,java,if-statement,hashmap,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 CheckingA
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
是包含(存款、网络、支票账户)的枚举;
bankAccounts
是一个HashMap,包含iban
(键)和检查帐户或存款帐户或网络帐户
;
CheckingAccounts
、DepositAccount
、WebAccount
是三个类,它们继承了名为Account
的抽象类
我试图用HashMap替换if
,该HashMap使用用户插入的字符串检查密钥(帐户类型),并实例化与HashMap中的密钥相关联的三个类中的一个。
问题是我无法创建字符串和帐户之间的对应关系,因为我需要实例化它(但我当时不知道cf)
有人能告诉我一些更好的方法来管理它吗?我建议不要使用任何类型的映射,因为它只会增加复杂性和运行时成本。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;
}
静态映射类型\u Map=newhashmap()
{
{AccountType.CHECKINGACCOUNT,CHECKINGACCOUNT.class},
{AccountType.DEPOSIT,DepositAccount.class},
{AccountType.WEB,WebAccount.class}
};
公共布尔addAccount(字符串cf,AccountType){
字符串iban=name+cf;
if(bankAccounts.containsKey(iban))返回false;
如果(!TYPE_MAP.containsKey(TYPE))返回false;
Class classType=TYPE\u MAP.get(TYPE);
Account=(Account)类类型
.getDeclaredConstructor(
String.class,
String.class,
整数(类)
.newInstance(cf,iban,0);
银行账户。put(iban,账户);
返回true;
}
为什么不使用工厂模式将要为哪个帐户创建的逻辑放在枚举本身中?自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);
}
与switch或map方法相比,这个解决方案有一个巨大的优势:如果您添加了一个新的子类和一个新的帐户类型,您就不会忘记处理这个新类型。其他解决方案将在运行时(而不是编译时)失败或给出错误的结果。我的观点是,从概念上讲,使用这种方法一切都很好。不过,我会稍微改变一下:
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;
}
我不认为有任何理由让使用反射或工厂来创建帐户实例变得更复杂。它不会给你带来任何好处,你只会得到更多的代码,新人会花更多的时间来理解它。我建议对类也使用泛型,
classs丑陋和低效的不是使用映射(顺便说一句,它应该是EnumMap)。丑陋的是反射的使用。如果在映射中存储工厂而不是存储类,则不需要反射。CHECKING(CheckingAccount::new)这里的CheckingAccount应该是CheckingAccountFactory吗?@IvanLymar No-CheckingAccount::new
是CheckingAccount
构造函数的一个参数。所有类都扩展了一个公共基类Account
——因此工厂只是一个AccountFactory
,有一个方法,它与每个扩展的构造函数具有相同的签名。@请参见您应该提到的,依我看,与switch或map方法相比,这个解决方案有一个巨大的优势:如果您添加了一个新的子类和一个新的帐户类型,您就不会忘记处理这个新类型。其他解决方案将在运行时失败,或给出不正确的结果