Over a million developers have joined DZone.

Strategy Design Pattern

·

Today I'm going to look at the Strategy Pattern, it's one of the more important design patterns in the GOF Pattern. In my previous post I discussed What is a  Design Pattern ?  and the basic background related to design patterns.

Which type of pattern ? 

It's categorized under Behavioral Pattern.

How GOF (Gang of four) Define it ?

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

How is it Used in the Real World ?

To explain the strategy in the real world, let's take the example. E-commerce has been a bit of a buzz word in the world today. Trading on the Internet is a hugely complex business and there are many aspects to consider when designing a successful e commerce site. In these websites when the customer buys  items  they are in the processing shopping cart. Many payment mechanisms are introduced to the Customers to dotheir  payment  Ex: Pay pal , Visa , Mobile payment some time according to the country wise there are payment mechanisms introduced  Ex: AUS  B-Pay. this real world scenario I'm get as the example :)

What is the Current Problem and  How to Solve it ? :O

In this scenario I need to maintain the different payment mechanisms in the e commerce site.  These payment methods are needed to separate each other because they have different process, but they do the same action (make the payment) to give the correct solution.  I need to follow mainly 3 design Principles.

Principles ?

1. I need to identify the aspects of my application that vary and separate them from what stays the same.

2. Program to an interface, not to an implementation.

3. Favor composition over inheritance

Ok next I go through the each principle

How to Design According to Principle ?

1. First I'm going to identify the three Payment types: Visa , Pay Pal and Mobile Payment.

2. In these payment method, do the same action (process the Customer Payment) but it's changed on the Run time according the Customer selection option.  For using OOP concepts, I'm going use  abstract class or an interface to create the opportunity to dynamic behavioral changes with the help of Polymorphism.

3. After creating the interface, I'm going to put more than one class together as class variables that is called composition,  then encapsulate payment methods into their
own set of classes. like Ex: Payment types Visa , Pay Pal

How it Can Design in the Design Level ?

Strategy Pattern Class Diagram

How to Implement it ?

Here I'll use Java Code to do my Sample Implementation.

PaymentMethod Interface

public interface PaymentMethod {
	public boolean pay(double amount);
}

Pay Pal Implementation

import java.util.Date;

public class PayPal implements PaymentMethod {

	private final String name;
	private final String cardNumber;
	private final Date expires;

	public String getName() {
		return name;
	}

	public String getCardNumber() {
		return cardNumber;
	}

	public Date getExpires() {
		return expires;
	}

	public PayPal(String name, String cardNumber, Date expires) {
		super();
		this.name = name;
		this.cardNumber = cardNumber;
		this.expires = expires;
	}

	@Override
	public boolean pay(double amount) {
		return true; // if payment goes through
	}
}

Visa Implementation

import java.util.Date;

public class Visa implements PaymentMethod {

	private final String name;
	private final String cardNumber;
	private final Date expires;

	public String getName() {
		return name;
	}

	public String getCardNumber() {
		return cardNumber;
	}

	public Date getExpires() {
		return expires;
	}

	public Visa(String name, String cardNumber, Date expires) {
		super();
		this.name = name;
		this.cardNumber = cardNumber;
		this.expires = expires;
	}

	@Override
	public boolean pay(double amount) {
		return true; // if payment goes through
	}
}

MobilePayment Implementation

import java.util.Date;

public class MobilePayment implements PaymentMethod {

	private final String serviceProvider;
	private final String mobileNumber;
	private final Date expires;

	public String getServiceProvider() {
		return serviceProvider;
	}

	public String getMobileNumber() {
		return mobileNumber;
	}

	public Date getExpires() {
		return expires;
	}

	public MobilePayment(String serviceProvider, String mobileNumber,
			Date expires) {
		super();
		this.serviceProvider = serviceProvider;
		this.mobileNumber = mobileNumber;
		this.expires = expires;
	}

	@Override
	public boolean pay(double amount) {
		return true; // if payment goes through
	}
}

There I'm implement the Item Class for the do this

Item Class

public class Item {
	private final String code;
	private final String name;
	private final Double price;

	public Item(String code, String name, Double price) {
		this.code = code;
		this.name = name;
		this.price = price;
	}

	public String getCode() {
		return code;
	}

	public String getName() {
		return name;
	}

	public Double getPrice() {
		return price;
	}
}

ShoppingCart Class

import java.util.ArrayList;
import java.util.List;

public class ShoppingCart {
	private final List items;

	public ShoppingCart() {
		items = new ArrayList();
	}

	public void addItem(Item item) {
		items.add(item);
	}

	public double calcTotalCost() {
		double total = 0.0;
		for (Item item : items) {
			total += item.getPrice();
		}
		return total;
	}

	public boolean pay(PaymentMethod method) {
		double totalCost = calcTotalCost();
		return method.pay(totalCost);
	}
}

SamplePayProcessTest Class

import static org.junit.Assert.*;

import java.util.Calendar;
import java.util.Date;

import org.junit.Test;

public class SamplePayProcessTest {
	@Test
	public void payBillUsingVisa() {

	  ShoppingCart instance = new ShoppingCart();

	  Item a = new Item("IT001","T-Shirt", 750.43);
	  instance.addItem(a);

	  Item b = new Item("IT002","hat", 102.99);
	  instance.addItem(b);

	  Date expiryDate = getCardExpireyDate();
	  PaymentMethod visa = new Visa("CaptainDebug", "1234234534564567", expiryDate);

	  boolean result = instance.pay(visa);
	  assertTrue(result);

	}

	private Date getCardExpireyDate() {
	  Calendar cal = Calendar.getInstance();
	  cal.clear();
		cal.set(2015, Calendar.JANUARY, 21);
		return cal.getTime();
	}
}

Conclusion

According to the given Solution, the behavior of a class should be defined at runtime, and easily maintaining each payment behavior if I need newa  payment method I can easily plug, without effecting to others.

This is the one of the sample scenarios we can address the Strategy Pattern in the real world, ok we will meet next day with another GOF design pattern. Thank you

Have a Nice Day :)

Topics:

Published at DZone with permission of Prathap Givantha Kalansuriya. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}