Decorator_装饰模式_PHP语言描述
来源:互联网 发布:淘宝运营应该做什么? 编辑:程序博客网 时间:2024/06/05 14:06
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
?>
- Decorator_装饰模式_PHP语言描述
- 设计模式-装饰者模式(Go语言描述)
- 设计模式c#语言描述——装饰(Decorator)模式
- 设计模式c#语言描述——装饰(Decorator)模式
- 设计模式c#描述——装饰(Decorator)模式
- 设计模式c#描述——装饰(Decorator)模式
- 设计模式C++描述----10.装饰(Decorator)模式
- 设计模式C++描述----10.装饰(Decorator)模式
- C语言设计模式:装饰模式
- 语言与模式-10装饰模式
- 设计模式-策略模式(Go语言描述)
- 设计模式-适配器模式(Go语言描述)
- 设计模式-命令模式(Go语言描述)
- 设计模式-代理模式(Go语言描述)
- 设计模式-适配器模式(Go语言描述)
- 装饰模式(Decorator)-----基于JAVA语言
- 单例模式详解JAVA语言描述
- go语言: 设计模式-代理模式(Go语言描述)
- 设计模式之原型模式
- 全负荷的 Node.js
- JBPM (六) compare decision with state
- 无刷新文件上传
- POJ 3286 How many 0's?
- Decorator_装饰模式_PHP语言描述
- C++函数重定义、重载、重写的区别
- EidtText设置字数输入限制的代码
- 设计模式之组合模式
- 父窗口调用iframe子窗口方法
- android三轴Gsensor方向
- Vijos P1484 ISBN号码
- C++ 对象指针
- jquery 操作select