Factory allows the consumer to create new objects without having to know the details of how they’re created, or what their dependencies are – they only have to give the information they actually want.

Account.java
abstract class Account {
abstract Integer calculateInterest();
}
CreditAccount.java
public class CreditAccount extends Account{
@Override
Integer calculateInterest() {
return 11;
}
}
SalaryAccount.java
public class SalaryAccount extends Account{
@Override
Integer calculateInterest() {
return 5;
}
}
SavingsAccount.java
public class SavingsAccount extends Account{
@Override
Integer calculateInterest() {
return 7;
}
}
AccountFactory.java
public class AccountFactory {
static Map<String, Account> hmAccountMap = new HashMap<>();
static {
hmAccountMap.put("SavingsAcc", new SavingsAccount());
hmAccountMap.put("CreditAcc", new CreditAccount());
hmAccountMap.put("SalaryAcc", new SalaryAccount());
}
public static Account getAccount(String accountType){
return hmAccountMap.get(accountType);
}
}
CalcInterest.java
public class CalcInterest{
public static void main(String[] args) {
Account objAccountFactory = AccountFactory.getAccount("SavingsAcc");
System.out.println("Interest rate is - " + Optional.of(objAccountFactory.calculateInterest()));
}
}
Using Streams for AccountFactory Class
AccountFactory.java
public static Optional<Account> getAccount(String accountType) {
return hmAccountMap.entrySet().stream()
.filter(accParam -> accParam.getKey().equals(accountType))
.findFirst()
.map(Map.Entry::getValue);
}
CalcInterest.java
public class CalcInterest{
public static void main(String[] args) {
Account objAccountFactory = AccountFactory.getAccount("SavingsAcc");
System.out.println("Interest rate is - " + Optional.of(objAccountFactory.calculateInterest()));
}
}
Output
Interest rate is - 7