Refactor if statement where i have to initialize different object
i'm searching the smartest way of handle this method
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
is enum that contains (DEPOSIT,WEB,CHECKINGACCOUNT);
bankAccounts
is an HashMap that contains iban
(key) & CheckingAccounts OR DepositAccount OR WebAccount
;
CheckingAccounts
,DepositAccount
,WebAccount
are 3 classes that inherit an abstract class called Account
.
I'm trying to substitute the if
with an HashMap that check the key (Type of account) with the String insert by the user and instantiates one of the three class associated to the key in the HashMap.
The problem is that i can't create the correspondence between the String and the Account because i need to instantiate that (but i don't know the cf in that moment)
Could someone show me some better way to manage it?
java if-statement hashmap
add a comment |
i'm searching the smartest way of handle this method
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
is enum that contains (DEPOSIT,WEB,CHECKINGACCOUNT);
bankAccounts
is an HashMap that contains iban
(key) & CheckingAccounts OR DepositAccount OR WebAccount
;
CheckingAccounts
,DepositAccount
,WebAccount
are 3 classes that inherit an abstract class called Account
.
I'm trying to substitute the if
with an HashMap that check the key (Type of account) with the String insert by the user and instantiates one of the three class associated to the key in the HashMap.
The problem is that i can't create the correspondence between the String and the Account because i need to instantiate that (but i don't know the cf in that moment)
Could someone show me some better way to manage it?
java if-statement hashmap
add a comment |
i'm searching the smartest way of handle this method
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
is enum that contains (DEPOSIT,WEB,CHECKINGACCOUNT);
bankAccounts
is an HashMap that contains iban
(key) & CheckingAccounts OR DepositAccount OR WebAccount
;
CheckingAccounts
,DepositAccount
,WebAccount
are 3 classes that inherit an abstract class called Account
.
I'm trying to substitute the if
with an HashMap that check the key (Type of account) with the String insert by the user and instantiates one of the three class associated to the key in the HashMap.
The problem is that i can't create the correspondence between the String and the Account because i need to instantiate that (but i don't know the cf in that moment)
Could someone show me some better way to manage it?
java if-statement hashmap
i'm searching the smartest way of handle this method
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
is enum that contains (DEPOSIT,WEB,CHECKINGACCOUNT);
bankAccounts
is an HashMap that contains iban
(key) & CheckingAccounts OR DepositAccount OR WebAccount
;
CheckingAccounts
,DepositAccount
,WebAccount
are 3 classes that inherit an abstract class called Account
.
I'm trying to substitute the if
with an HashMap that check the key (Type of account) with the String insert by the user and instantiates one of the three class associated to the key in the HashMap.
The problem is that i can't create the correspondence between the String and the Account because i need to instantiate that (but i don't know the cf in that moment)
Could someone show me some better way to manage it?
java if-statement hashmap
java if-statement hashmap
asked Nov 23 '18 at 18:41
FabioFabio
94111
94111
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Why not put the logic for which Account to create right in the enum itself, using a factory pattern? Ever since Java 8, this pattern is really slick, as you can literally pass in the constructor as an implementation of the factory:
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);
}
This solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime (instead of compile time)
CHECKING(CheckingAccount::new) should CheckingAccount here be CheckingAccountFactory?
– Ivan Lymar
Nov 23 '18 at 19:24
@IvanLymar No -CheckingAccount::new
is a lambda expression to theCheckingAccount
constructor. All classes extend a common base classAccount
- so the factory is just anAccountFactory
, with a single method that has the same signature as the constructors for each of the extensions.
– Krease
Nov 23 '18 at 19:29
1
@Krease what you should mention, IMO, is that this solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime.
– JB Nizet
Nov 23 '18 at 19:31
Well said @JBNizet :)
– Krease
Nov 23 '18 at 19:33
add a comment |
I would advise against using any sort of type map as it just increases complexity and runtime cost. A switch statement seems the easiest.
Here is an example:
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;
}
However, if you are determined to use a type map:
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;
}
I would suggest to use generic for Class too,Class<? extends Account>
, and if constructor usesint
useint.class
– azro
Nov 23 '18 at 19:00
1
What's ugly and inefficient is not the use of a Map (which should be an EnumMap, BTW). What's ugly is the use of reflection. If you stored a Factory in the map instead of storing the class, you wouldn't need reflection.
– JB Nizet
Nov 23 '18 at 19:01
add a comment |
My opinion is that conceptually everything is fine with this method. I would change it a bit though:
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;
}
I do not see any reasons to make it more complex using reflection or factories to create acount instances. It will not give you any benefit, you will just get more code and new person will spend more time to understand it.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53451601%2frefactor-if-statement-where-i-have-to-initialize-different-object%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Why not put the logic for which Account to create right in the enum itself, using a factory pattern? Ever since Java 8, this pattern is really slick, as you can literally pass in the constructor as an implementation of the factory:
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);
}
This solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime (instead of compile time)
CHECKING(CheckingAccount::new) should CheckingAccount here be CheckingAccountFactory?
– Ivan Lymar
Nov 23 '18 at 19:24
@IvanLymar No -CheckingAccount::new
is a lambda expression to theCheckingAccount
constructor. All classes extend a common base classAccount
- so the factory is just anAccountFactory
, with a single method that has the same signature as the constructors for each of the extensions.
– Krease
Nov 23 '18 at 19:29
1
@Krease what you should mention, IMO, is that this solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime.
– JB Nizet
Nov 23 '18 at 19:31
Well said @JBNizet :)
– Krease
Nov 23 '18 at 19:33
add a comment |
Why not put the logic for which Account to create right in the enum itself, using a factory pattern? Ever since Java 8, this pattern is really slick, as you can literally pass in the constructor as an implementation of the factory:
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);
}
This solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime (instead of compile time)
CHECKING(CheckingAccount::new) should CheckingAccount here be CheckingAccountFactory?
– Ivan Lymar
Nov 23 '18 at 19:24
@IvanLymar No -CheckingAccount::new
is a lambda expression to theCheckingAccount
constructor. All classes extend a common base classAccount
- so the factory is just anAccountFactory
, with a single method that has the same signature as the constructors for each of the extensions.
– Krease
Nov 23 '18 at 19:29
1
@Krease what you should mention, IMO, is that this solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime.
– JB Nizet
Nov 23 '18 at 19:31
Well said @JBNizet :)
– Krease
Nov 23 '18 at 19:33
add a comment |
Why not put the logic for which Account to create right in the enum itself, using a factory pattern? Ever since Java 8, this pattern is really slick, as you can literally pass in the constructor as an implementation of the factory:
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);
}
This solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime (instead of compile time)
Why not put the logic for which Account to create right in the enum itself, using a factory pattern? Ever since Java 8, this pattern is really slick, as you can literally pass in the constructor as an implementation of the factory:
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);
}
This solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime (instead of compile time)
edited Nov 23 '18 at 19:33
answered Nov 23 '18 at 19:13
KreaseKrease
11.6k74160
11.6k74160
CHECKING(CheckingAccount::new) should CheckingAccount here be CheckingAccountFactory?
– Ivan Lymar
Nov 23 '18 at 19:24
@IvanLymar No -CheckingAccount::new
is a lambda expression to theCheckingAccount
constructor. All classes extend a common base classAccount
- so the factory is just anAccountFactory
, with a single method that has the same signature as the constructors for each of the extensions.
– Krease
Nov 23 '18 at 19:29
1
@Krease what you should mention, IMO, is that this solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime.
– JB Nizet
Nov 23 '18 at 19:31
Well said @JBNizet :)
– Krease
Nov 23 '18 at 19:33
add a comment |
CHECKING(CheckingAccount::new) should CheckingAccount here be CheckingAccountFactory?
– Ivan Lymar
Nov 23 '18 at 19:24
@IvanLymar No -CheckingAccount::new
is a lambda expression to theCheckingAccount
constructor. All classes extend a common base classAccount
- so the factory is just anAccountFactory
, with a single method that has the same signature as the constructors for each of the extensions.
– Krease
Nov 23 '18 at 19:29
1
@Krease what you should mention, IMO, is that this solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime.
– JB Nizet
Nov 23 '18 at 19:31
Well said @JBNizet :)
– Krease
Nov 23 '18 at 19:33
CHECKING(CheckingAccount::new) should CheckingAccount here be CheckingAccountFactory?
– Ivan Lymar
Nov 23 '18 at 19:24
CHECKING(CheckingAccount::new) should CheckingAccount here be CheckingAccountFactory?
– Ivan Lymar
Nov 23 '18 at 19:24
@IvanLymar No -
CheckingAccount::new
is a lambda expression to the CheckingAccount
constructor. All classes extend a common base class Account
- so the factory is just an AccountFactory
, with a single method that has the same signature as the constructors for each of the extensions.– Krease
Nov 23 '18 at 19:29
@IvanLymar No -
CheckingAccount::new
is a lambda expression to the CheckingAccount
constructor. All classes extend a common base class Account
- so the factory is just an AccountFactory
, with a single method that has the same signature as the constructors for each of the extensions.– Krease
Nov 23 '18 at 19:29
1
1
@Krease what you should mention, IMO, is that this solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime.
– JB Nizet
Nov 23 '18 at 19:31
@Krease what you should mention, IMO, is that this solution has a huge advantage over the switch or map approach: if you ever add a new subclass and a new type of account, there is no way you can forget to handle this new type. The other solutions will fail, or give incorrect results, at runtime.
– JB Nizet
Nov 23 '18 at 19:31
Well said @JBNizet :)
– Krease
Nov 23 '18 at 19:33
Well said @JBNizet :)
– Krease
Nov 23 '18 at 19:33
add a comment |
I would advise against using any sort of type map as it just increases complexity and runtime cost. A switch statement seems the easiest.
Here is an example:
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;
}
However, if you are determined to use a type map:
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;
}
I would suggest to use generic for Class too,Class<? extends Account>
, and if constructor usesint
useint.class
– azro
Nov 23 '18 at 19:00
1
What's ugly and inefficient is not the use of a Map (which should be an EnumMap, BTW). What's ugly is the use of reflection. If you stored a Factory in the map instead of storing the class, you wouldn't need reflection.
– JB Nizet
Nov 23 '18 at 19:01
add a comment |
I would advise against using any sort of type map as it just increases complexity and runtime cost. A switch statement seems the easiest.
Here is an example:
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;
}
However, if you are determined to use a type map:
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;
}
I would suggest to use generic for Class too,Class<? extends Account>
, and if constructor usesint
useint.class
– azro
Nov 23 '18 at 19:00
1
What's ugly and inefficient is not the use of a Map (which should be an EnumMap, BTW). What's ugly is the use of reflection. If you stored a Factory in the map instead of storing the class, you wouldn't need reflection.
– JB Nizet
Nov 23 '18 at 19:01
add a comment |
I would advise against using any sort of type map as it just increases complexity and runtime cost. A switch statement seems the easiest.
Here is an example:
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;
}
However, if you are determined to use a type map:
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;
}
I would advise against using any sort of type map as it just increases complexity and runtime cost. A switch statement seems the easiest.
Here is an example:
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;
}
However, if you are determined to use a type map:
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;
}
answered Nov 23 '18 at 18:58
AlchemyAlchemy
4253
4253
I would suggest to use generic for Class too,Class<? extends Account>
, and if constructor usesint
useint.class
– azro
Nov 23 '18 at 19:00
1
What's ugly and inefficient is not the use of a Map (which should be an EnumMap, BTW). What's ugly is the use of reflection. If you stored a Factory in the map instead of storing the class, you wouldn't need reflection.
– JB Nizet
Nov 23 '18 at 19:01
add a comment |
I would suggest to use generic for Class too,Class<? extends Account>
, and if constructor usesint
useint.class
– azro
Nov 23 '18 at 19:00
1
What's ugly and inefficient is not the use of a Map (which should be an EnumMap, BTW). What's ugly is the use of reflection. If you stored a Factory in the map instead of storing the class, you wouldn't need reflection.
– JB Nizet
Nov 23 '18 at 19:01
I would suggest to use generic for Class too,
Class<? extends Account>
, and if constructor uses int
use int.class
– azro
Nov 23 '18 at 19:00
I would suggest to use generic for Class too,
Class<? extends Account>
, and if constructor uses int
use int.class
– azro
Nov 23 '18 at 19:00
1
1
What's ugly and inefficient is not the use of a Map (which should be an EnumMap, BTW). What's ugly is the use of reflection. If you stored a Factory in the map instead of storing the class, you wouldn't need reflection.
– JB Nizet
Nov 23 '18 at 19:01
What's ugly and inefficient is not the use of a Map (which should be an EnumMap, BTW). What's ugly is the use of reflection. If you stored a Factory in the map instead of storing the class, you wouldn't need reflection.
– JB Nizet
Nov 23 '18 at 19:01
add a comment |
My opinion is that conceptually everything is fine with this method. I would change it a bit though:
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;
}
I do not see any reasons to make it more complex using reflection or factories to create acount instances. It will not give you any benefit, you will just get more code and new person will spend more time to understand it.
add a comment |
My opinion is that conceptually everything is fine with this method. I would change it a bit though:
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;
}
I do not see any reasons to make it more complex using reflection or factories to create acount instances. It will not give you any benefit, you will just get more code and new person will spend more time to understand it.
add a comment |
My opinion is that conceptually everything is fine with this method. I would change it a bit though:
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;
}
I do not see any reasons to make it more complex using reflection or factories to create acount instances. It will not give you any benefit, you will just get more code and new person will spend more time to understand it.
My opinion is that conceptually everything is fine with this method. I would change it a bit though:
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;
}
I do not see any reasons to make it more complex using reflection or factories to create acount instances. It will not give you any benefit, you will just get more code and new person will spend more time to understand it.
answered Nov 23 '18 at 19:19
Ivan LymarIvan Lymar
920315
920315
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53451601%2frefactor-if-statement-where-i-have-to-initialize-different-object%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown