卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章16554本站已运行3318

策略模式:设计模式中的一种

策略模式:设计模式中的一种

到目前为止,我们已经介绍了本系列中的三种设计模式。我们定义了四类不同的设计模式。在本文中,我将解释策略设计模式,它属于行为设计模式

你可能有一个问题:什么时候应该使用这种设计模式?我想说,当我们有多种方法(算法)来执行相同的操作,并且我们希望应用程序根据您拥有的参数选择特定的方法时。这种模式也称为策略模式。

本文的一个非常简单的示例是排序功能。例如,我们有多种对数组进行排序的算法,但是根据数组元素的数量,我们应该选择使用哪种算法来获得最佳性能。

此模式也称为策略模式。

问题

我将举一个集成了多个支付网关的电子商务网站的例子。尽管该网站有多个支付网关,但根据要求,它们不会全部显示在前端。相反,需要根据购物车金额即时选择适当的支付网关。

举个简单的例子,如果购物车价值低于 500 美元,则应使用 PayPal 标准处理付款,但如果金额为 500 美元或以上,则应使用存储的信用卡详细信息进行处理(假设详细信息已存储)。

如果没有实施正确的策略,我们的代码将如下所示:

首先,我们将提供通过 Paypal 支付和通过信用卡支付的主要类,这些类将在下面添加。

// 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);
}

在这里,您可能会说我们需要放置条件语句才能使我们的代码正常工作。想象一下,当我们需要对该逻辑进行新的更改或者您发现该逻辑中的错误时,您需要进行多少更改。我们必须向所有使用该代码的地方添加补丁。

解决方案

我们将实现相同的要求,但使用策略模式,这使我们能够使我们的代码更加清晰、易于理解和可扩展。

界面

首先,我们将实现所有不同支付网关类将使用的接口。最终,这些是我们的策略。

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);
		
	}
}

在这里我们可以看到我们的付款方式的条件加载是在 payAmount 方法中完成的。让我们将所有内容包装在一起,看看如何进一步使用它。

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

我们可以看到支付网关的翻转对于应用程序来说并不透明。根据参数,它有适当的支付网关可用于处理交易。

添加新策略

如果在后期用户需要添加具有不同逻辑的新策略(此处为新支付网关),在这种情况下会非常简单。假设我们要添加一个新的支付网关 Moneybooker,并希望在购物车金额超过 500 美元但低于 1,000 美元时处理资金。

我们需要做的就是创建一个新的策略类来实现我们的接口,我们就可以开始了。

class payByMB implements payStrategy {

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

}

我们现在已经准备好了新的策略类,我们需要更改的是主要的 payAmount 方法。需要修改如下:

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);
}

在这里您可以看到我们仅在 payAmount 方法中进行了更改,而不是在调用该方法的客户端代码中进行了更改。

结论

因此得出结论,当我们有多种方法来执行同一任务时(在软件语言中,当我们有多种算法来执行同一操作时),我们应该考虑实现策略模式。

通过使用这种模式,我们可以自由地添加/删除算法,因为这些算法的切换对于应用程序来说并不透明。

我已尽力提供一个基本但有用的示例来演示策略设计模式,但如果您有其他意见或问题,请随时将它们添加到下面的提要中。

卓越飞翔博客
上一篇: 如何在C/C++中使用枚举?
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏