Wednesday 27 August 2014

Bridge Design Pattern Implementation

Bridge Design Pattern

The purpose of Bridge design pattern is "decouple abstraction from implementation". This pattern uses encapsulation, aggregation, and can use inheritance to separate responsibilities into separate classes.

Benefits:-

1. Hiding implementation details
2. Helping to improve extensibility and maintainability
3. Helping to share implementation among several clients.   

Difference between Adapter design pattern and Bridge design pattern :

Adapter is used to adapt to an existing interface by delegating the request to adaptee where as Bridge is designed upfront to let the abstraction and the implementation vary independently.
For example:- Think about the Payment Gateway System

reference taken from http://www.slideshare.net/nyrostechnologies/payment-gateway-1509260

Here we can see that payment gateway is working as a bridge between Merchant and Acquiring Bank. Now we will implement the same concept in programming.

1. Payment.java

package com.gaurav.designpattern.bridge;

import java.util.HashMap;

/**
 * @author gaurav
 *
 */

public interface Payment {
public boolean verifyBankCardDetails(HashMap<String, String> cardDetailsMap);
public boolean authorizeTransaction(HashMap<String, String> cardDetailsMap);
public String getPayment(HashMap<String, String> cardDetailsMap);
}

2. EcommerceMerchantWebsite.java

package com.gaurav.designpattern.bridge;

import java.util.HashMap;

/**
 * @author gaurav
 *
 */
public class EcommerceMerchantWebsite{
HashMap<String, String> cardDetails = new HashMap<String, String>();

public EcommerceMerchantWebsite(HashMap<String, String> cardDetailsMap) {
this.cardDetails = cardDetailsMap;
}
public EcommerceMerchantWebsite(){}
public String callPaymentGateway() {
PaymentGateway paymentGateway = new PaymentGateway();
String paymentStatusByGateway = paymentGateway.getPayment(cardDetails);
System.out
.println("Transaction status received by Gateway is : "
+ paymentStatusByGateway);
return paymentStatusByGateway;
}
public boolean getPaymentStatus(String status){
boolean flag = false;
if("Success".equalsIgnoreCase(status)){
System.out.println("Payment received successfully by Merchant");
flag = true;
}
return flag;
}
public void itemsPurchasedStatus(boolean amountReceivedFlag){
if(amountReceivedFlag == true){
System.out.println("Online purchase done successfully - at Ecommerce Website");
}
}
}

3. AcquiringBank.java

package com.gaurav.designpattern.bridge;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

/**
 * @author gaurav
 *
 */
public class AcquiringBank implements Payment{

@Override
public boolean verifyBankCardDetails(HashMap<String, String> cardDetailsMap) {
boolean verifyFlag = false;
try {

String cardNumber = cardDetailsMap.get("CardNumber");
boolean isParsable = isParsableToLong(cardNumber);

String cvvNumber = cardDetailsMap.get("CVV");
boolean isParsableCvv = isParsableToInteger(cvvNumber);

String expiryDate = cardDetailsMap.get("ExpiryDate");
SimpleDateFormat sdf = new SimpleDateFormat("MM/yy");
Date date = sdf.parse(expiryDate);

if (isParsable && cardNumber.length() == 16) {

System.out.println("This is a valid card number - validated By Bank");

if (isParsableCvv && cvvNumber.length() == 3) {
System.out.println("This CVV number is also valid - validated By Bank");

if (date.after(new Date())) {
System.out.println("Given expiry date is after date compare to the current date - validated By Bank");
verifyFlag = true;
}
}
}else{
System.out.println("Card validation failed by Bank");
}
} catch (ParseException pse) {
System.out.println("Exception occurs while parsing the date"
+ pse.getMessage());
}catch (Exception e) {
System.out.println("Exception occurs during verification : "
+ e.getMessage());
}
return verifyFlag;
}
@Override
public String getPayment(HashMap<String, String> cardDetailsMap) {
boolean authFlag = authorizeTransaction(cardDetailsMap);
String status = "Failed";
if(authFlag){
System.out.println("Payment is approved successfully - by Bank");
status = "Success";
}
return status;
}

@Override
public boolean authorizeTransaction(HashMap<String, String> cardDetailsMap) {
boolean authFlag = false;
boolean checkVerification = verifyBankCardDetails(cardDetailsMap);
if(checkVerification){
System.out.println("Card authorization done successfully - by Bank");
authFlag = true;
}
return authFlag;
}
public boolean isParsableToInteger(String strValue) {
        try {
            Integer.parseInt(strValue);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }
public boolean isParsableToLong(String strValue) {
        try {
        Long.parseLong(strValue);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }
}

4. PaymentGateway.java

package com.gaurav.designpattern.bridge;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

/**
 * @author gaurav
 *
 */
public class PaymentGateway implements Payment{
@Override
public boolean verifyBankCardDetails(HashMap<String, String> cardDetailsMap) {
boolean verifyFlag = false;
try {

String cardNumber = cardDetailsMap.get("CardNumber");
boolean isParsable = isParsableToLong(cardNumber);

String cvvNumber = cardDetailsMap.get("CVV");
boolean isParsableCvv = isParsableToInteger(cvvNumber);

String expiryDate = cardDetailsMap.get("ExpiryDate");
SimpleDateFormat sdf = new SimpleDateFormat("MM/yy");
Date date = sdf.parse(expiryDate);

if (isParsable && cardNumber.length() == 16) {

System.out.println("This is a valid card number - validated By Payment Gateway");

if (isParsableCvv && cvvNumber.length() == 3) {
System.out.println("This CVV number is also valid - validated By Payment Gateway");

if (date.after(new Date())) {
System.out.println("Given expiry date is after date compare to the current date - validated By Payment Gateway");
verifyFlag = true;
}
}
}else{
System.out.println("Card validation failed by Payment Gateway");
}
} catch (ParseException pse) {
System.out.println("Exception occurs while parsing the date"
+ pse.getMessage());
}catch (Exception e) {
System.out.println("Exception occurs during verification : "
+ e.getMessage());
}
return verifyFlag;
}
@Override
public String getPayment(HashMap<String, String> cardDetailsMap) {
System.out.println("Connectivity started by Payment Gateway between Merchant and Bank for online purchase");
boolean authFlag = authorizeTransaction(cardDetailsMap);
String status = "Failed";
AcquiringBank acquiringBank = new AcquiringBank();
if(authFlag){
System.out.println("Payment process is forwarded successfully to bank - By Payment Gateway");
status = "Success";
String statusFromBank = acquiringBank.getPayment(cardDetailsMap);
if(statusFromBank.equalsIgnoreCase(status)){
System.out.println("Payment is approved by the Bank and credited at Merchant Account");
}
}
return status;
}

@Override
public boolean authorizeTransaction(HashMap<String, String> cardDetailsMap) {
boolean authFlag = false;
boolean checkVerification = verifyBankCardDetails(cardDetailsMap);
if(checkVerification){
System.out.println("Card validation done successfully - By Payment Gateway");
authFlag = true;
}
return authFlag;
}
public boolean isParsableToInteger(String strValue) {
        try {
            Integer.parseInt(strValue);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }
public boolean isParsableToLong(String strValue) {
        try {
        Long.parseLong(strValue);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }
}

5. BridgeDesignPatternDemo.java

package com.gaurav.designpattern.bridge;

import java.util.HashMap;

/**
 * @author gaurav
 * 
 */
public class BridgeDesignPatternDemo {
public static void main(String args[]) {

HashMap<String, String> cardDetails = new HashMap<String, String>();
cardDetails.put("CardNumber", "2134567821345698");
cardDetails.put("CVV", "012");
cardDetails.put("ExpiryDate", "10/15");
EcommerceMerchantWebsite ecommerceMerchantWebsite = new EcommerceMerchantWebsite(cardDetails);
String paymentStatusByGateway = ecommerceMerchantWebsite.callPaymentGateway();
EcommerceMerchantWebsite ecomMerchantWebsite = new EcommerceMerchantWebsite();
boolean amountReceivedFlag = ecomMerchantWebsite
.getPaymentStatus(paymentStatusByGateway);
ecomMerchantWebsite.itemsPurchasedStatus(amountReceivedFlag);
}
}

Result :-

Connectivity started by Payment Gateway between Merchant and Bank for online purchase
This is a valid card number - validated By Payment Gateway
This CVV number is also valid - validated By Payment Gateway
Given expiry date is after date compare to the current date - validated By Payment Gateway
Card validation done successfully - By Payment Gateway
Payment process is forwarded successfully to bank - By Payment Gateway
This is a valid card number - validated By Bank
This CVV number is also valid - validated By Bank
Given expiry date is after date compare to the current date - validated By Bank
Card authorization done successfully - by Bank
Payment is approved successfully - by Bank
Payment is approved by the Bank and credited at Merchant Account
Transaction status received by Gateway is : Success
Payment received successfully by Merchant
Online purchase done successfully - at Ecommerce Website

2 comments: