2017-11-10 12:02:47 2015次浏览 2条回答 0 悬赏 50 金钱

先介绍业务场景:

销售型业务,售卖材料的。比如,地砖,地板,油漆,等等
但是公司卖这些东西的价格会有不同,例如遇到节假日会打折,满多少钱会打折。买了数量多优惠等等。

我首先想到了是策略模式

自己硬着头皮设计了一个结构,希望大牛帮帮忙看看这么设计的行吗?
首先,文件结构如下图:
![2220A889-E3B4-4DCD-96E2-4FA126497F8E.png](/uploads/images/201711/10115339566.png "2220A889-E3B4-4DCD-96E2-4FA126497F8E.png")
源码目录:

https://github.com/CoderShawnZhang/Strategy

大神下来看看可以吗?

调用:
//$dizhuan = new Dizhuan();
$diban = new Diban();
$priceStractegy = new FivezhePrice();//五折计价

$dimian = new Dimian($diban,$priceStractegy);
$dimian->getPrice();

  • 回答于 2017-11-13 20:02 举报
    <?php
    // 促销抽象类 (Component: 组件对象接口)
    abstract class Promotion {
    	public $price; // 统计优惠价格
    	// 计算价格
    	abstract public function calePrice();
    }
    
    
    // 原始订单 (ConcreteComponent: 具体的组件对象, 实现了组件接口, 被装饰器装饰的原始对象)
    class Order extends Promotion {
    	public $goodsInfo;
    	public function __construct ($goodsInfo) {
    		$this->goodsInfo = $goodsInfo;
    	}
    	
    	public function calePrice() {
    		// 计算商品价格
    		foreach($this->goodsInfo as $key=>$val) {
    			$this->price += $val['price'];
    		}
    		return $this->price;
    	}
    }
    
    // 装饰器: 父类 (Decorator: 所有装饰器的父类, 需要定义一个与组件接口一致的接口)
    class Decorator extends Promotion {
    	public $promotion;
    	public $goodsInfo;
    
    	public function __construct(Promotion $promotion) {
    		$this->promotion = $promotion;
    		$this->goodsInfo = $promotion->goodsInfo;
    	}
    	public function calePrice(){
    	}
    }
    
    // 装饰器: 代金券 (ConcreteDecorator: 具体的装饰器类)
    class CashCoupon extends Decorator {
    	public function calePrice() {
    		foreach($this->goodsInfo as $key=>$val) {
    			if($val['couponType'] == 1) {
    				$this->price += $val['couponVal'];
    			}
    		}
    
    		return $this->promotion->calePrice() - $this->price;
    	}
    }
    // 装饰器: 打折券 (ConcreteDecorator: 具体的装饰器类)
    class DiscountCoupon extends Decorator {
    	public function calePrice(){
    		foreach($this->goodsInfo as $key=>$val) {
    			if($val['couponType'] == 2) {
    				$this->price += $val['price'] * (1 - $val['couponVal']);
    			}
    		}
    
    		return $this->promotion->calePrice() - $this->price;
    	}
    }
    // 装饰器: 免单券 (ConcreteDecorator: 具体的装饰器类)
    class FreeCoupon extends Decorator {
    	public function calePrice(){
    		foreach($this->goodsInfo as $key=>$val) {
    			if($val['couponType'] == 3) {
    				$this->price += $val['price'];
    			}
    		}
    
    		return $this->promotion->calePrice() - $this->price;
    	}
    }
    // 装饰器: 满减 (ConcreteDecorator: 具体的装饰器类)
    class MoneyOff extends Decorator {
    	// 满减规则, atLeastAmount: 满减金额, amountOff: 减免金额/优惠金额
    	private $moneyOffRules = [
    		['atLeastAmount'=> 1000, 'amountOff'=> 10, 'start'=>0, 'end'=>1000],
    		['atLeastAmount'=> 2000, 'amountOff'=> 20, 'start'=>1000, 'end'=>2000],
    		['atLeastAmount'=> 3000, 'amountOff'=> 30, 'start'=>2000, 'end'=>3000],
    		['atLeastAmount'=> 4000, 'amountOff'=> 40, 'start'=>3000, 'end'=>4000],
    	];
    	public function calePrice() {
    		$price = $this->promotion->calePrice();
    		foreach($this->moneyOffRules as $key=>$val) {
    			if($price >= $val['start'] and $price < $val['end']) {
    				$this->price = $val['amountOff'];
    			}
    		}
    		return $price - $this->price;
    	}
    }
    // couponType: 优惠券类型( 1-代金券, 2-折扣券, 3-免单券)
    // couponVal : 优惠金额或折扣
    
    $goodsInfo = [
    	['id'=>1, 'goodsName'=>'商品01', 'price'=>1000, 'couponType'=>1, 'couponVal'=>100],
    	['id'=>2, 'goodsName'=>'商品02', 'price'=>1000, 'couponType'=>2, 'couponVal'=>0.5],
    	['id'=>3, 'goodsName'=>'商品03', 'price'=>1000, 'couponType'=>3, 'couponVal'=>0],
    	['id'=>4, 'goodsName'=>'商品04', 'price'=>1000, 'couponType'=>0, 'couponVal'=>0],
    	['id'=>5, 'goodsName'=>'商品05', 'price'=>1000, 'couponType'=>2, 'couponVal'=>0.6],
    ];
    $order = new Order($goodsInfo); // 5000
    $order = new CashCoupon($order); // 使用优惠方式: 代金券 4900
    $order = new DiscountCoupon($order); // 使用优惠方式: 打折券 4000
    $order = new FreeCoupon($order); // 使用优惠方式: 免单券 3000
    $order = new MoneyOff($order); // 使用优惠方式: 满减 2960
    
    echo $order->calePrice(); // 3000
    
  • 回答于 2017-11-10 17:24 举报

    哪能一个产品就声明一个类?说一下我的方法:订单总金额由物品金额和服务金额两部分组成。你说的“满减”、“节假日优惠”等都可以算进服务。假设地砖的价格是 5元/块,明天就是双十一了,你想搞个促销——消费满 500 元减50元。你可以新建一个服务,该服务的计费逻辑是看物品金额是否大于等于 500,是则新建一条金额为 -50 的服务记录。

    假设客人买了 100 块, 付款金额 = 5x100 (物品金额)-50 (服务金额)= 450. 说得有些笼统,我之前做过一个类似的项目,如果你有兴趣,可以详细讨论。

    1 条回复
    回复于 2017-11-10 21:24 回复

    谢谢你,我借鉴一下试试

    觉得很赞
您需要登录后才可以回答。登录 | 立即注册
灰太狼
副总裁

灰太狼

注册时间:2016-11-19
最后登录:2023-07-14
在线时长:76小时17分
  • 粉丝28
  • 金钱3290
  • 威望150
  • 积分5550

热门问题