装饰模式定义:
装饰模式是在不改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
装饰模式角色:
抽象构件(Component)角色:定义一个对象接口,可以给这些对象动态地添加职责。
具体构件角色:定义一个将要接收附加职责的类。
装饰角色:持有一个Component对象,并定义一个与Component接口一致的接口。
具体装饰角色:负责给构件对象增加额外的职责。
在电商平台,常常会用到红包,优惠券,打折等促销活动,客户在实际支付时需要减去促销部分的金额,这里只考虑一次支付只能使用一种优惠,那么可以将订单金额看作是被装饰的对象,红包,优惠券等看作是装饰对象。
本代码使用Yii2.0实现
抽象构件:
<?php namespace common\services; use Yii; /** * 定义金额接口 * Interface AmountInterface * * @package common\services */ interface AmountInterface { /** * 获取支付金额 * @return mixed */ public function getPayAmount(); }
具体构件:
<?php namespace common\services; use common\services\AmountInterface; use Yii; /** * 金额具体类 * Class PayAmountService * * @package common\services */ class PayAmountService implements AmountInterface { /** * 获取支付金额 * @return int */ public function getPayAmount() { $orderAmount = 100; return $orderAmount; } }
装饰角色:
<?php namespace common\services; use common\services\AmountInterface; use Yii; /** * 装饰类父类 * Class DecoratorAmountService * * @package common\services */ abstract class DecoratorAmountService implements AmountInterface { protected $component; public function __construct(AmountInterface $component) { $this->component = $component; } /** * 获取支付金额 * @return mixed */ public function getPayAmount() { return $this->component->getPayAmount(); } } 具体装饰角色:
<?php namespace common\services; use common\services\DecoratorAmountService; use Yii; /** * 优惠券类 * Class CouponAmountService * * @package common\services */ class CouponAmountService extends DecoratorAmountService { public function __construct(AmountInterface $component) { parent::__construct($component); } /** * 获取支付金额 * * @return int|mixed */ public function getPayAmount() { $amount = parent::getPayAmount(); $couponAmount = $this->getCouponAmount(); return $amount - $couponAmount; } /** * 获取优惠券金额 * * @return int */ public function getCouponAmount() { $amount = 10; return $amount; } }
<?php namespace common\services; use common\services\DecoratorAmountService; use Yii; /** * 红包类 * Class RedbagAmountService * * @package common\services */ class RedbagAmountService extends DecoratorAmountService { public function __construct(AmountInterface $component) { parent::__construct($component); } /** * 获取支付金额 * * @return int|mixed */ public function getPayAmount() { $amount = parent::getPayAmount(); $redbagAmount = $this->getRedbagAmount(); return $amount - $redbagAmount; } /** * 获取红包金额 * * @return int */ public function getRedbagAmount() { $amount = 5; return $amount; } }
测试:
<?php namespace backend\controllers; use common\services\PayAmountService; use common\services\CouponAmountService; use common\services\RedbagAmountService; use Yii; use yii\web\Controller; class DecoratorTestController extends Controller { /** * 测试 */ public function actionIndex() { $compent = new PayAmountService(); $couponObj = new CouponAmountService($compent); $redbagObj = new RedbagAmountService($compent); $payAmount = $couponObj->getPayAmount(); echo 'use coupon,payamount:'.$payAmount; $payAmount = $redbagObj->getPayAmount(); echo 'use redbag,payamount:'.$payAmount; } }