Google

Mar 22, 2013

Java design pattern interview questions and answers: strategy and factory pattern

Design pattern questions are very popular with the job interviewers, and this post covers Java strategy and factory design pattern in a tutorial style. This blog takes you through a scenario where you will be learning 4 key things.

1. Factory design pattern
2. Strategy design pattern
3. Applying logic to calculate variance
4. Making use of the BigDecimal class for the financial calculations. The floating point variables must not be used as they can cause rounding issues.

Q. The scenario is narrated with the diagram below. It is financial application where an investor builds portfolio by buying and selling managed funds and listed securities.



The additional business rules are:

1. The managed funds that are not of type daily, must be funded from the available cash. Which means, you cannot use the proceeds you receive from selling managed funds or listed securities.

2. The daily managed funds and listed securities can be switched. This means you sell some daily managed funds to buy some listed securities.

3. The variance is calculated as total sell amount - total buy amount. The funded from cash amount also needs to be calculated to show the investor.

Let's look at the code samples:


Step 1: Define the InvestmentDetail value object (i.e. a POJO) that defines each investment  detail as shown above.

import java.math.BigDecimal;

public class InvestmentDetail {
 
 enum TRADE_TYPE {BUY, SELL};
 enum FUND_TYPE {MONTHLY, DAILY, NOT_APPLICABLE}
 
 private String investmentCode;
 private String investmentName;
 private TRADE_TYPE tradeType;
 private FUND_TYPE fundType;
 private BigDecimal orderAmount;
 
 public InvestmentDetail(String investmentCode, String investmentName, 
                   TRADE_TYPE tradeType, FUND_TYPE fundType, BigDecimal orderAmount) {
  this.investmentCode = investmentCode;
  this.investmentName = investmentName;
  this.tradeType = tradeType;
  this.fundType = fundType;
  this.orderAmount = orderAmount;
 }
 
 public boolean isDailyManagedFund() {
  return fundType != null && fundType == FUND_TYPE.DAILY;
 }
 
 public boolean isMonthlyManagedFund() {
  if(fundType == null  ) {
   throw new IllegalArgumentException("fundType cannot be null");
  }
  return fundType == FUND_TYPE.MONTHLY;
 }
 
 public boolean isListedSecurity() {
  return fundType != null && fundType == FUND_TYPE.NOT_APPLICABLE;
 }
 
 public boolean isBuy() {
  if(tradeType == null  ) {
   throw new IllegalArgumentException("tradeType cannot be null");
  }
  return tradeType == TRADE_TYPE.BUY;
 }
 
 public boolean isSell() {
  if(tradeType == null  ) {
   throw new IllegalArgumentException("tradeType cannot be null");
  }
  return tradeType == TRADE_TYPE.SELL;
 }

 public BigDecimal getOrderAmount() {
  return orderAmount;
 }
 
 //setters, getters, equals(), hashCode(), and toString() omitted for brevity
}

Step 2: The CashVariance value object (i.e. a POJO) for storing the calculated values like funded from cash and proceed to cash amounts and the variance is derived from these two amounts.

import java.math.BigDecimal;


public class CashVariance {

 BigDecimal fundedFromCash;
 BigDecimal proceedsToCash;
 
 public CashVariance(BigDecimal fundedFromCash, BigDecimal proceedsToCash) {
  super();
  this.fundedFromCash = fundedFromCash;
  this.proceedsToCash = proceedsToCash;
 }

 public BigDecimal getVariance() {
  return this.proceedsToCash.subtract(this.fundedFromCash);
 }
 
 public void setFundedFromCash(BigDecimal fundedFromCash) {
  this.fundedFromCash = fundedFromCash;
 }

 public void setProceedsToCash(BigDecimal proceedsToCash) {
  this.proceedsToCash = proceedsToCash;
 }

 public String toString() {
  StringBuilder buffer = new StringBuilder();
  buffer.append("fromCash:").append(this.fundedFromCash);
  buffer.append("|toCash:").append(this.proceedsToCash);
  buffer.append("|variance:").append(getVariance());
  return buffer.toString();
 }
 
 //getters, equals(), and hashCode()omitted for brevity
}


Step 3: Define a factory class that decides which cash variance calculation strategy to use depending on the product type.

//cannot be extended as it is final
public final class VarianceCalculationFactory {
 
 //can't instantiate from outside
 private VarianceCalculationFactory(){}
 
 //factory that creates and return a relevant strategy
 public static CashVarianceCalculationStrategy getCashVarianceStrategy(String productType) {
  if(productType != null ) {
   return new SpecificCashVarianceCalculationStrategy();
  }
  else {
   return new DefaultCashVarianceCalculationStrategy();
  }
 }

}


Q. Why use a factory design pattern?
A.
Factory pattern returns an instance of several subclasses (like DefaultCashVarianceCalculationStrategy, ManagedInvestmentsCashVarianceCalculationStrategy, etc), but the calling code is unaware of the actual implementation class. The calling code invokes the method on the interface for example CashVarianceCalculationStrategy and using polymorphism the relevant class and correct method gets invoked. So, as you can see, the factory pattern reduces the coupling or the dependencies between the calling code and called objects like DefaultCashVarianceCalculationStrategy, ManagedInvestmentsCashVarianceCalculationStrategy, etc. This is a very powerful and common feature in many frameworks.  You do not have to create a new DefaultCashVarianceCalculationStrategy or a new ManagedInvestmentsCashVarianceCalculationStrategy on each invocation. In future, to conserve memory, you can decide to cache objects or reuse objects in your factory with no changes required to your calling code. You can also load objects in your factory based on attribute(s) read from an external properties file or some other condition. Another benefit going for the factory is that unlike calling constructors directly, factory patterns have more meaningful names like getShape(…), getInstance(…), getStrategy(…) etc, which may make calling code much clear. 



Step 4: Define an interface each strategy class will be implementing.

import java.util.List;

//strategy pattern interface
public interface CashVarianceCalculationStrategy {
 CashVariance calculate (List<InvestmentDetail> investments);
}


Step 5: This is the default implementation of the above interface, and the class that is responsible for calculating the funded from cash and proceed to cash values.




import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;

public class DefaultCashVarianceCalculationStrategy implements CashVarianceCalculationStrategy {

 @Override
 public CashVariance calculate(List<InvestmentDetail> investments) {
  //input validation
  if(investments == null){
   throw new IllegalArgumentException("No investments founds!!!");
  }
  
  List<BigDecimal> buys = new LinkedList<BigDecimal>();
     List<BigDecimal> sells = new LinkedList<BigDecimal>(); 
     List<BigDecimal> switchables = new LinkedList<BigDecimal>(); //pay for buys from the sells
  
  for (InvestmentDetail detail : investments) {
   if(detail.isBuy()){
    processBuy(detail, buys, switchables);
   }
   else if(detail.isSell()){
    processSell(detail, sells, switchables); 
   }
  }
  
  CashVariance variance = calculateVariance(buys, sells, switchables);
  
  return variance;
 }

 private void processSell(InvestmentDetail detail, List<BigDecimal> sells, List<BigDecimal> switchables) {
  if(isSwitch(detail)){
   switchables.add(detail.getOrderAmount()); //+ve amount
  }
  else{
   sells.add(detail.getOrderAmount());
  }
  
 }

 private void processBuy(InvestmentDetail detail, List<BigDecimal> buys, List<BigDecimal> switchables) {
  if(isSwitch(detail)){
   switchables.add(detail.getOrderAmount().negate());  //-ve amount
  }
  else{
   buys.add(detail.getOrderAmount());
  }
  
 }

 //protected so that it can be overridden by another strategy
 protected boolean isSwitch(InvestmentDetail detail){
  return detail != null && (detail.isDailyManagedFund() || detail.isListedSecurity()); //return false if it is a monthly managed fund
                                                                                       //This has to be funded from cash.
 }
 
 protected CashVariance calculateVariance(List<BigDecimal> buys, List<BigDecimal> sells, List<BigDecimal> switchables) {
  BigDecimal switchedSum = sumAll(switchables);
  BigDecimal fundedFromCash = calculateFundedFromCash(buys, switchedSum);
  BigDecimal proceedsToCash = calculateProceedsToCash(sells, switchedSum);
  
  return new CashVariance(fundedFromCash, proceedsToCash);
 }
 
 private BigDecimal calculateFundedFromCash(List<BigDecimal> buys, BigDecimal switchedSum) {
  BigDecimal buysSum = sumAll(buys);
  //if switchedSum has more buy amount (i.e negative) add the switchedSum to buy
  return buysSum.add((switchedSum.signum() == -1) ? switchedSum.abs() : BigDecimal.ZERO);
 }

 private BigDecimal calculateProceedsToCash(List<BigDecimal> sells, BigDecimal switchedSum) {
  BigDecimal sellsSum = sumAll(sells);
  //if switchedSum has more sell amount (i.e positive) add the switchedSum to sell 
  return sellsSum.add((switchedSum.signum() == 1) ? switchedSum : BigDecimal.ZERO);
 }

 
 private BigDecimal sumAll(List<BigDecimal> values) {
  BigDecimal total = BigDecimal.ZERO;
  for (BigDecimal val : values) {
   total = total.add(val);
  }
  return total;
 } 

}

Q. Why use a strategy design pattern?
A.  A strategy design pattern allows you to choose different algorithms at run time depending certain run time conditions like product type. Different algorithms can be isolated in different implementation classes that implement the same interface. Different client classes or invokees can execute different strategies (i.e. algorithms).

Step 6: Finally, the tester class that demonstrates the  above scenario by constructing investment details and calculating the variance as shown below.


import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;

public class VarianceCalcTester {

 public static void main(String[] args) {
  InvestmentDetail ab0001 = new InvestmentDetail("AB0001", "AB Manged Fund", 
                                          InvestmentDetail.TRADE_TYPE.BUY, InvestmentDetail.FUND_TYPE.MONTHLY, 
                                          new BigDecimal("2500.00"));
  
  InvestmentDetail cx0002 = new InvestmentDetail("CX0002", "CX Managed Fund", 
                InvestmentDetail.TRADE_TYPE.BUY, InvestmentDetail.FUND_TYPE.DAILY, 
                new BigDecimal("4500.00"));
  
  InvestmentDetail by007 = new InvestmentDetail("BY007", "BY Managed Fund", 
                InvestmentDetail.TRADE_TYPE.BUY, InvestmentDetail.FUND_TYPE.DAILY, 
                new BigDecimal("2000.00"));
  
  
  InvestmentDetail sh0008 = new InvestmentDetail("SH0008", "BY Managed Fund", 
                InvestmentDetail.TRADE_TYPE.SELL, InvestmentDetail.FUND_TYPE.NOT_APPLICABLE, 
                new BigDecimal("8000.00"));
  
  List<InvestmentDetail> investments = new LinkedList<InvestmentDetail>();
  
  investments.add(ab0001);
  investments.add(cx0002);
  investments.add(by007);
  investments.add(sh0008);
  
  
  //get the variance calculation strategy from the factory

  CashVarianceCalculationStrategy cvCalcStaregy = VarianceCalculationFactory.getCashVarianceStrategy(null); // return the default strategy
  
  CashVariance cv = cvCalcStaregy.calculate(investments);
  
  
  System.out.println(cv); // -ve variance Debit  and +ve variance Credit
 }
}


Labels:

6 Comments:

Anonymous Anonymous said...

i am not understand this sir. please explain this wit diagrams.

7:57 PM, May 25, 2014  
Blogger Unknown said...

it is an advanced real life example. Try coding it yourself to better understand.

10:22 AM, May 26, 2014  
Anonymous Anonymous said...

thank you sir.. What is the difference between Strategy and command design pattern?, It looks like both are same

3:29 PM, June 24, 2014  
Blogger Unknown said...

Many design patterns look similar, but the intent is different. Have a look at this post http://java-success.blogspot.com.au/2014/06/why-do-proxy-decorator-adapter-facade.html from core Java tutorial which discusses subtle differences between some of the design patterns with diagrams and examples.

4:17 PM, June 24, 2014  
Blogger Unknown said...

Stay tuned, and I will post a blog on difference between Command and strategy design patterns with examples.

6:34 PM, June 24, 2014  
Anonymous Anonymous said...

Thanks you

2:08 AM, June 25, 2014  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home