Sunday 18 May 2014

Strategy Design Pattern



Strategy Design Pattern:-
Initialization of the strategy generally falls into two categories: application or factory-based.
Application-based initialization depends on the application to create the implementation itself and cast it to the interface. It is hard-coded so difficult to swap the strategy. This appears to the application like:
      ICardBuilderStrategy cardStrategy  =  new MasterCardBuilderStrategy();
                cardStrategy.pay();

Factory-based initialization defines a factory which contains different implementations and appropriate implementation is getting returned. Switching strategy is very easy with this. This looks like:
      ICardBuilderStrategy cardStrategy  =   CardStrategyFactory.getCardBuilderStrategyInstance("Master");
                cardStrategy.pay();

Example:-
Trying to explain the Strategy pattern here with the help of credit card example as below:
ICardBuilderStrategy.java
/**
 * It is basically a policy to decide the card payment algorithm on run-time as per client request
 */
public interface ICardBuilderStrategy {

      /**
       * @param card
       * @return
       */
      public boolean pay(CardData card);
}

AbstractCardBuilderStrategy
import java.util.Date;

public abstract class AbstractCardBuilderStrategy implements ICardBuilderStrategy{

      @Override
      public abstract boolean pay(CardData card);

      public boolean isCardValid(String authorizationCode, Date CreditCardExpirationDate){
            //validation logic to check if card is valid may be w.r.t. Database
            return true;
      }
}

MasterCardBuilderStrategy.java
/**
 * Strategy to pay for Master
 */
public class MasterCardBuilderStrategy extends AbstractCardBuilderStrategy {

      @Override
      public boolean pay(CardData card){
           
            if(isCardValid(card.getAuthorizationId(), card.getCreditCardExpirationDate())){
                  //business logic for payment here specifically Master Card
                  return true;
            }
            return false;
      }
}

VisaCardBuilderStrategy.java
/**
 * Strategy to pay for Visa
 */
public class VisaCardBuilderStrategy extends AbstractCardBuilderStrategy {

      @Override
      public boolean pay(CardData card){
           
            if(isCardValid(card.getAuthorizationId(), card.getCreditCardExpirationDate())){
                  //business logic for payment here specifically Visa Card
                  return true;
            }
            return false;
      }
}

Context.java
/**
 * Configured with a ConcreteStrategy object and maintains
 * a reference to a Strategy object
 */
public class Context {

      private ICardBuilderStrategy strategy;
     
      public Context(ICardBuilderStrategy strategy) {
        this.strategy = strategy;
    }
     
      /**
       * @param emp
       */
    public boolean executeStrategy(CardData card) {
        return this.strategy.pay(card);
    }
}


CardStrategyFactory.java

public final class CardStrategyFactory {

      /**
       * @param cardBuilderStrategyName
       * @return
       */
      public static ICardBuilderStrategy getCardBuilderStrategyInstance(String cardBuilderStrategyName){
           
            if("Master".equals(cardBuilderStrategyName.toLowerCase())){
                  return new MasterCardBuilderStrategy();
            }
            else if("Visa".equals(cardBuilderStrategyName.toLowerCase())){
                  return new VisaCardBuilderStrategy();
            }
            return null;
      }
}

CardData.java
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class CardData {

      private String authorizationId;
      private Date creditCardExpirationDate;
      private String CreditCardName;
      private String CreditCardNo;
     
      /** Card Type : Visa, Master **/
      private String CreditCardType;
     
      private String Currency;
      private String EnterpriseCode;

      /** Max. Credit card amount **/
      private double totalCreditAmount;

      /** Requested amount for transaction **/
      private double RequestAmount;

      /** Amount which credit card holder suppose to pay **/
      private double pendingAmount;

      /** Time-frame for any transaction on which fee will not be applicable **/
      private String gracePeriod;

      /** Date of a transaction **/
      private Date requestAmountDate;

      /** Transaction Map: key as date and value as requested amount **/
      private Map<Date, Double> transactionMap = new HashMap<Date, Double>();

      private String sCVVAuthCode;

      /** Possible values: APPROVED, DECLINED, SERVICE_UNAVAILABLE **/
      private String tranReturnCode;

      public String getAuthorizationId() {
            return authorizationId;
      }
      public void setAuthorizationId(String authorizationId) {
            this.authorizationId = authorizationId;
      }
      public Date getCreditCardExpirationDate() {
            return creditCardExpirationDate;
      }
      public void setCreditCardExpirationDate(Date creditCardExpirationDate) {
            this.creditCardExpirationDate = creditCardExpirationDate;
      }
      public String getCreditCardName() {
            return CreditCardName;
      }
      public void setCreditCardName(String creditCardName) {
            CreditCardName = creditCardName;
      }
      public String getCreditCardNo() {
            return CreditCardNo;
      }
      public void setCreditCardNo(String creditCardNo) {
            CreditCardNo = creditCardNo;
      }
      public String getCreditCardType() {
            return CreditCardType;
      }
      public void setCreditCardType(String creditCardType) {
            CreditCardType = creditCardType;
      }
      public String getCurrency() {
            return Currency;
      }
      public void setCurrency(String currency) {
            Currency = currency;
      }
      public String getEnterpriseCode() {
            return EnterpriseCode;
      }
      public void setEnterpriseCode(String enterpriseCode) {
            EnterpriseCode = enterpriseCode;
      }
      public String getsCVVAuthCode() {
            return sCVVAuthCode;
      }
      public void setsCVVAuthCode(String sCVVAuthCode) {
            this.sCVVAuthCode = sCVVAuthCode;
      }
      public String getTranReturnCode() {
            return tranReturnCode;
      }
      public void setTranReturnCode(String tranReturnCode) {
            this.tranReturnCode = tranReturnCode;
      }
      public String getGracePeriod() {
            return gracePeriod;
      }
      public void setGracePeriod(String gracePeriod) {
            this.gracePeriod = gracePeriod;
      }
      public Date getRequestAmountDate() {
            return requestAmountDate;
      }
      public void setRequestAmountDate(Date requestAmountDate) {
            this.requestAmountDate = requestAmountDate;
      }
      public Map<Date, Double> getTransactionMap() {
            return transactionMap;
      }
     
      public void setTransactionMap(Date transDate, Double requestAmount) {
            if(this.transactionMap.containsKey(transDate)){
                  requestAmount += this.transactionMap.get(transDate);       
            }
            this.transactionMap.put(transDate, requestAmount);
      }
     
      public void setTotalCreditAmount(double totalCreditAmount) {
            this.totalCreditAmount = totalCreditAmount;
      }
      public void setRequestAmount(double requestAmount) {
            RequestAmount = requestAmount;
      }
      public void setPendingAmount(double pendingAmount) {
            this.pendingAmount = pendingAmount;
      }
      public double getTotalCreditAmount() {
            return totalCreditAmount;
      }
      public double getRequestAmount() {
            return RequestAmount;
      }
      public double getPendingAmount() {
            return pendingAmount;
      }

}

Client.java
public class Client {

      public static void main(String[] args) {
           
            CardData card = new CardData();
            //set card data using their setter method
            cardPay(card);
      }
     
      private static void cardPay(CardData card) {
           
            /** card.getCreditCardType() decides which strategy will be in action **/
            boolean isPaid = new Context(CardStrategyFactory.getCardBuilderStrategyInstance(card.getCreditCardType())).executeStrategy(card);
            System.out.println(card.getCreditCardType() + " card payment Success : "+ isPaid);
      }
}

No comments:

Post a Comment