策略模式详解编程语言

需求:银行收银系统,营业员根据客户所购买商品的单价和数量,向客户收费。其中有几种模式:原价模式、打折模式、满减模式,每一种商品在结账的时候都要选择一种模式进行对应,且模式中的值有不同。

根据需求,准备以下不同的类。

一、抽象策略接口

interface Strategy 
{ 
    public function getResult(); 
}

二、原价策略类

class Cash implements Strategy 
{ 
    protected $price; 
    protected $amount; 
 
    public function __construct($price,$amount) 
    { 
        $this->price = $price; 
        $this->amount = $amount; 
    } 
 
    public function getResult() 
    { 
        return $this->price * $this->amount; 
    } 
}

三、打折策略类

class Discount implements Strategy 
{ 
    protected $price; 
    protected $amount; 
    protected $rate; 
 
    public function __construct($price,$amount,$rate) 
    { 
        $this->price = $price; 
        $this->amount = $amount; 
        $this->rate = $rate; 
    } 
 
    public function getResult() 
    { 
        return $this->price * $this->amount * $this->rate; 
    } 
}

四、满减策略类

class Rebate implements Strategy 
{ 
    protected $price; 
    protected $amount; 
    protected $rule; 
 
    public function __construct($price,$amount,$rule) 
    { 
        $this->price = $price; 
        $this->amount = $amount; 
        $this->rule = $rule; 
    } 
 
    public function getResult() 
    { 
        $money = $this->price * $this->amount; 
        $result = self::_minusMoney($money,$this->rule); 
 
        return $result; 
    } 
 
    /** 
     * 计算满减后的金额 
     * @param $money 
     * @param $rule 
     * @return mixed 
     */ 
    private function _minusMoney($money,$rule) 
    { 
        $result = $money - floor($money/$rule[0]) * $rule[1]; 
        return $result; 
    } 
}

五、上下文类

class Context 
{ 
    private $strategy; 
    public function __construct(Strategy $strategy) 
    { 
        $this->strategy = $strategy; 
    } 
 
    public function countResult() 
    { 
        return $this->strategy->getResult(); 
    } 
}

六、简单工厂类

class Factory 
{ 
    public static function createObj($params) 
    { 
        $obj = null; 
 
        $price = $params['price']; 
        $amount = $params['amount']; 
        $discount = isset($params['discount'])?$params['discount']:1; 
        $rule = isset($params['rule'])?$params['rule']:[]; 
 
        switch($params['type']) 
        { 
            case 1: 
                $obj = new Cash($price,$amount); 
                break; 
            case 2: 
                $obj = new Discount($price,$amount,$discount); 
                break; 
            case 3: 
                $obj = new Rebate($price,$amount,$rule); 
                break; 
        } 
 
        return $obj; 
    } 
}

七、测试代码如下:

$result = 0; 
 
$params = [ 
    'type'=>1, 
    'price'=>12, 
    'amount'=>5 
]; 
$strategy_cash = new Context(Factory::createObj($params)); 
echo '原价商品,费用为:',$strategy_cash->countResult(); 
$result += $strategy_cash->countResult(); 
 
$params = [ 
    'type'=>2, 
    'price'=>12, 
    'amount'=>5, 
    'discount'=>0.8 
]; 
$strategy_discount = new Context(Factory::createObj($params)); 
echo '打折商品,费用为:',$strategy_discount->countResult(); 
$result += $strategy_cash->countResult(); 
 
$params = [ 
    'type'=>3, 
    'price'=>120, 
    'amount'=>5, 
    'rule'=>[300,40] 
]; 
$strategy_rebate = new Context(Factory::createObj($params)); 
echo '满减商品,费用为:',$strategy_rebate->countResult(); 
 
$result += $strategy_cash->countResult(); 
echo '总费用为:',$result;

八、UML图如下:

策略模式详解编程语言

 

总结:

1. 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

2. 当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。将这些行为封装在一个个独立的Strategy类中,可以在使用这些行为的类中消除条件语句。

3. 策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/16894.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论