Home > Backend Development > PHP Tutorial > Strategy pattern: one of the design patterns

Strategy pattern: one of the design patterns

PHPz
Release: 2023-08-28 17:54:01
Original
1045 people have browsed it

Strategy pattern: one of the design patterns

So far, we have covered three design patterns in this series. We define four different categories of design patterns. In this article, I will explain the Strategic Design Pattern, which falls under the Behavioral Design Patterns.

You may have a question: When should you use this design pattern? I would say when we have multiple methods (algorithms) to perform the same operation and we want the application to choose a specific method based on the parameters you have. This mode is also called strategy mode.

A very simple example for this article is the sorting function. For example, we have multiple algorithms for sorting arrays, but depending on the number of array elements, we should choose which algorithm to use to get the best performance.

This mode is also called strategy mode.

question

I will give an example of an e-commerce website that integrates multiple payment gateways. Although the website has multiple payment gateways, upon request, they are not all displayed on the front-end. Instead, the appropriate payment gateway needs to be selected on the fly based on the cart amount.

As a simple example, if the cart value is less than $500, the payment should be processed using PayPal standards, but if the amount is $500 or more, it should be processed using the stored credit card details (assuming the details have been storage).

Without the correct strategy implemented, our code would look like this:

First we will provide the main classes for payment via Paypal and payment via credit card, which will be added below.

// Class to pay using Credit Card
class payByCC {

    private $ccNum = '';
	private $ccType = '';
	private $cvvNum = '';
	private $ccExpMonth = '';
	private $ccExpYear = '';
	
	public function pay($amount = 0) {
		echo "Paying ". $amount. " using Credit Card";
	}
	
}

// Class to pay using PayPal
class payByPayPal {

	private $payPalEmail = '';
	
	public function pay($amount = 0) {
		echo "Paying ". $amount. " using PayPal";
	}

}

// This code needs to be repeated every place where ever needed.
$amount  = 5000;
if($amount >= 500) {
	$pay = new payByCC();
	$pay->pay($amount);
} else {
	$pay = new payByPayPal();
	$pay->pay($amount);
}
Copy after login

Here, you might say that we need to put conditional statements to make our code work properly. Imagine how many changes you need to make when we need to make new changes to this logic or you find a bug in this logic. We have to add patches to all places where this code is used.

solution

We will implement the same requirement, but using the Strategy pattern, which allows us to make our code clearer, easier to understand and extensible.

interface

First, we will implement the interfaces that all the different payment gateway classes will use. Ultimately, these are our strategies.

interface payStrategy {
    public function pay($amount);
}

class payByCC implements payStrategy {
	
	
	private $ccNum = '';
	private $ccType = '';
	private $cvvNum = '';
	private $ccExpMonth = '';
	private $ccExpYear = '';
	
	public function pay($amount = 0) {
		echo "Paying ". $amount. " using Credit Card";
	}
	
}

class payByPayPal implements payStrategy {

	private $payPalEmail = '';
	
	public function pay($amount = 0) {
		echo "Paying ". $amount. " using PayPal";
	}

}
Copy after login

Next we will create our main class, which can use different strategies than the ones we have implemented so far.

class shoppingCart {
    	
	public $amount = 0;
	
	public function __construct($amount = 0) {
		$this->amount = $amount;
	}
	
	public function getAmount() {
		return $this->amount;
	}
	
	public function setAmount($amount = 0) {
		$this->amount = $amount;
	}

	public function payAmount() {
		if($this->amount >= 500) {
			$payment = new payByCC();
		} else {
			$payment = new payByPayPal();
		}
		
		$payment->pay($this->amount);
		
	}
}
Copy after login

Here we can see that the conditional loading of our payment method is done in the payAmount method. Let's wrap everything together and see how to use it further.

interface payStrategy {
    public function pay($amount);
}

class payByCC implements payStrategy {
	
	private $ccNum = '';
	private $ccType = '';
	private $cvvNum = '';
	private $ccExpMonth = '';
	private $ccExpYear = '';
	
	public function pay($amount = 0) {
		echo "Paying ". $amount. " using Credit Card";
	}
	
}

class payByPayPal implements payStrategy {

	private $payPalEmail = '';
	
	public function pay($amount = 0) {
		echo "Paying ". $amount. " using PayPal";
	}

}

class shoppingCart {
	
	public $amount = 0;
	
	public function __construct($amount = 0) {
		$this->amount = $amount;
	}
	
	public function getAmount() {
		return $this->amount;
	}
	
	public function setAmount($amount = 0) {
		$this->amount = $amount;
	}

	public function payAmount() {
		if($this->amount >= 500) {
			$payment = new payByCC();
		} else {
			$payment = new payByPayPal();
		}
		
		$payment->pay($this->amount);
	}
}

$cart = new shoppingCart(499);
$cart->payAmount();

// Output
Paying 499 using PayPal

$cart = new shoppingCart(501);
$cart->payAmount();

//Output 
Paying 501 using Credit Card
Copy after login

We can see that the payment gateway rollover is not transparent to the application. Depending on the parameters, it has the appropriate payment gateway available to process the transaction.

Add new strategy

If at a later stage the user needs to add a new strategy with different logic (here a new payment gateway), it will be very simple in this case. Let’s say we want to add a new payment gateway, Moneybooker, and want to process funds when the cart amount exceeds $500 but falls below $1,000.

All we need to do is create a new strategy class that implements our interface and we are good to go.

class payByMB implements payStrategy {

    private $mbEmail = '';
	
	public function pay($amount = 0) {
		echo "Paying ". $amount. " using Money Booker";
	}

}
Copy after login

We now have our new strategy class ready, all we need to change is the main payAmount method. Need to be modified as follows:

public function payAmount() {
    
	if($this->amount > 500 && $this->amount < 1000) {
		$payment = new payByMB();
	} else if($this->amount >= 500) {
		$payment = new payByCC();
	} else {
		$payment = new payByPayPal();
	}
	
	$payment->pay($this->amount);
}
Copy after login

Here you can see that we only made the change in the payAmount method, not in the client code that calls the method.

in conclusion

So to conclude, when we have multiple ways to perform the same task (in software languages, when we have multiple algorithms to perform the same operation), we should consider implementing the Strategy pattern.

By using this mode, we can add/remove algorithms freely since the switching of these algorithms is not transparent to the application.

I've tried my best to provide a basic but useful example to demonstrate the Strategy Design Pattern, but if you have additional comments or questions, please feel free to add them to the feed below.

The above is the detailed content of Strategy pattern: one of the design patterns. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template