zoukankan      html  css  js  c++  java
  • 策略模式

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

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

    一、抽象策略接口

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

  • 相关阅读:
    面向对象
    原型链
    HTTP协议
    java连接数据库(jdbc)调用配置文件
    MySQL-学习笔记
    JAVA-集合框架
    JAVA-多线程
    java中的try-catch-finally异常处理(学习笔记)
    ADO.NET增、删、改、查
    C#资源管理器
  • 原文地址:https://www.cnblogs.com/gspsuccess/p/9231139.html
Copyright © 2011-2022 走看看