Decorator_装饰模式_PHP语言描述

本文介绍如何使用装饰模式来灵活地实现奖金计算体系。通过PHP代码示例展示了如何为销售人员的奖金计算添加不同的奖励类型,如当月业务奖金和个人累计奖金。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Decorator_装饰模式的定义:

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更加灵活。

应用Decorator_装饰模式解决问题的思路:

考虑这样一个应用场景,即灵活的实现奖金的计算。在实际的应用中,很多公司对于销售人员的奖金计算方式五花本门,并且经常变动。是非常复杂的。

首先是奖金的分类,对于个人大致有个人当月业务奖金、个人累计奖金、个人业务增长奖金、及时回款奖金等等。

其次是计算奖金的金额,又有这么几个基数,销售额,销售毛利,实际回款,业务成本,奖金基数等。

看了上面奖金的计算问题,大家是不是觉得特别的头疼,这里我们只讨论设计模式,并不真正要去实现整体的业务。简化一下,演示用的奖金计算体系如下:

每个人当月业务奖金 = 当月销售额 * 3%;

每个人累计奖金 = 累计销售额 * 0.1%;

团队奖金 = 团队总销售额 * 1%;

根据装饰模式的定义来看,要用这个模式解决此业务问题,我们需要如下的结构:

Component:组件对象接口,可以给这些对象动态的添加职责

ConcreteComponent:具体的组件对象,实现组建对象接口,通常就是被装饰器装饰的原始对象,也就是可以给这个对象添加职责。

Decorator:所有装饰器类的抽象父类,需要定义一个与组件接口一致的接口,并持有一个Component对象,  其实就是持有一个被装饰的对象.

ConcreteDecorator:实际的装饰器对象,实现具体要向被装饰对象添加的功能。

注意:这个被装饰的对象不一定是最原始的那个对象了,也可能是被其他装饰器装饰过后的装饰器对象,反正都是实现的同一个接口,也就是同一类型。

001 <?php
002 /**
003  * Decorator_装饰模式_PHP语言描述
004  */
005  
006 /**
007  * 计算奖金的组建接口
008  */
009 abstract class Component{
010     /**
011      * 计算某人在某阶段内的奖金,有些参数在演示中并不会使用
012      * 但在实际业务实现上会用的,为了表示这是个具体的业务方法,因此这些参数被保留了。
013      * @param $user
014      * @param $begin
015      * @param $end
016      * <a href="http://my.oschina.net/u/556800" class="referer" target="_blank">@return</a>  int 某人在某段时间内的奖金
017      */
018     public abstract  function calcPrize($user,$begin,$end);
019 }
020  
021 /**
022  * 基本的实现计算奖金的类,也是被装饰器装饰的对象
023  */
024 class ConcreteComponent extends Component{
025     public function calcPrize($user$begin$end){
026         //只是一个默认的实现,默认没有奖金
027         return 0;
028     }
029 }
030  
031  
032 class TempDB{
033      
034     static $SaleMoneyList array('zs'=>10000,'ls'=>20000,'ww'=>30000);
035      
036     public static function getMonthSaleMoney($user){
037         return TempDB::$SaleMoneyList[$user];
038     }
039 }
040  
041 /**
042  * 装饰器的接口,需要和被装饰的对象实现同样的接口
043  */
044 abstract class Decorator extends Component{
045     /**
046      * 持有被装饰的组建对象
047      */
048     protected $c;
049     /**
050      * 通过构造方法传入被装饰的对象
051      * @param c 被装饰的对象
052      */
053     public function __construct($c){
054         $this->c = $c;
055     }
056      
057     public function calcPrize($user$begin$end){
058         //转调组件对象的方法
059         return $this->c->calcPrize($user,$begin,$end);
060     }
061 }
062  
063 /**
064  * 装饰器对象,计算当月业务奖金
065  */
066 class MonthPrizeDecorator extends Decorator{
067     public function __construct($c){
068         parent::__construct($c);
069     }
070      
071     public function calcPrize($user$begin$end){
072         //1.先获取前面运算出来的奖金
073         $money = parent::calcPrize($user$begin$end);
074         //2.然后计算当月业务奖金,按人员和时间去获取当月业务额,然后再乘以3%
075         $prize = TempDB::getMonthSaleMoney($user) * 0.03;
076         echo $user."当月业务奖金:".$prize."<br>";
077         return $money+$prize;
078     }
079 }
080  
081 /**
082  * 装饰器对象,计算累计奖金
083  */
084 class SumPrizeDecorator extends Decorator{
085     public function __construct($c){
086         parent::__construct($c);
087     }
088      
089     public function calcPrize($user$begin$end){
090         //1.先获取前面运算出来的奖金
091         $money = parent::calcPrize($user$begin$end);
092         //2.然后计算累计奖金,其实应该按照人员去获取累计的业务额,然后再乘以0.1%
093         //简单演示一下,假定大家累计的业务额都是1000000元
094         $prize = 1000000 * 0.001;
095         echo $user."累计业务奖金:".$prize."<br>";
096         return $money $prize;
097     }
098 }
099 //先创建计算基本奖金的类,这也是被修饰的类
100 $c1 new ConcreteComponent();
101  
102 //然后对计算的基本奖金进行装饰,这里要组合各个装饰
103 //说明,各个装饰者之间最好是不要有先后顺序的限制
104 //也就是先装饰谁和后装饰谁都应该是一样的
105  
106 //组合普通业务人员的奖金计算
107 $d1 new MonthPrizeDecorator($c1);
108 $d2 new SumPrizeDecorator($d1);
109  
110 //注意:这里只需要使用最后组合好的对象调用业务方法即可,会依次调用回去
111 //日期对象都没有用上,所以传NULL就可以了
112 $zs $d2->calcPrize('zs', null, null);
113 echo '============张三应得的奖金:'.$zs."<br>";
114 $ls $d2->calcPrize('ls', null, null);
115 echo '============李四应得的奖金:'.$ls."<br>";
116 ?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值