我正在寻找处理此方法的最聪明的方法
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 WebAccount
;
CheckingAccounts
,DepositAccount
,WebAccount
是3个类,它们继承了称为Account
的抽象类。
我正在尝试用HashMap替换if
,该HashMap由用户使用String插入检查密钥(帐户类型),并实例化与HashMap中的密钥相关联的三个类之一。
问题是我无法在String和Account之间创建对应关系,因为我需要实例化该实例(但那一刻我不知道cf)
有人可以告诉我一些更好的方法来管理它吗?
答案 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实例使其变得更加复杂。它不会给您带来任何好处,您只会获得更多的代码,而新用户将花费更多的时间来理解它。