PHP面向对象编程组合模式与装饰模式

本文介绍了PHP面向对象编程的组合模式和装饰模式:

组合模式

定义:组合模式定义了一个单一的继承系统,这样一组完全不同的职责可以并肩工作。

军人案件,


< PHP
抽象类单元
摘要bombardstrength()函数;
}
类弓箭手扩展单位{ / /。
功能bombardstrength(){
返回4;
}
}
类lasercannonunit扩展单元{ / /手枪
功能bombardstrength(){
返回44;
}
}
>




陆军综合成员,输出火力


< PHP
抽象类单元{
摘要bombardstrength()函数;
}
类弓箭手扩展单位{
功能bombardstrength(){
返回4;
}
}
类lasercannonunit扩展单元{
功能bombardstrength(){
返回44;
}
}
班军{ / /军
私有=数组($单位);定义私有的单个属性集
功能addunit(单位美金){ / /添加成员
array_push(美元->单位,单位美元);
}
功能(bombardstrength){ / /火
0美元;
foreach(美元->单位为美元单位){
($ ret = $单位-> bombardstrength);
}
返回$;
}
}
1美元=新射手();
2美元=新lasercannonunit();
陆军=新军();
军> addunit美元(合写);
军> addunit美元($ 2);
打印(元军-> bombardstrength); / /输出功率
>




输出:

四十八

军队进一步整合了其他部队。


< PHP
抽象类单元{
摘要bombardstrength()函数;
}
类弓箭手扩展单位{
功能bombardstrength(){
返回4;
}
}
类lasercannonunit扩展单元{
功能bombardstrength(){
返回44;
}
}
班军{
私有$单位=数组();
私人$军队=阵列();
功能addunit(单位美金){
array_push(美元->单位,单位美元);
}
功能addarmy(军元军){
array_push(美元->军队,元军);
}
功能bombardstrength(){
0美元;
foreach(美元->单位为美元单位){
($ ret = $单位-> bombardstrength);
}
foreach(美元->军队达军){
($ ret = $军-> bombardstrength);
}
返回$;
}
}
1美元=新射手();
2美元=新lasercannonunit();
陆军=新军();
军> addunit美元(合写);
军> addunit美元($ 2);
印军-> bombardstrength(美元);
打印;
陆军2美元/美元=克隆克隆人军队的军队;
军> addarmy美元($陆军2);
印军-> bombardstrength(美元);
打印;
>




输出:

四十八

九十六

支持新功能、删除功能和其他功能的更好方法。


< PHP
抽象类单元{
摘要功能addunit(单位为单位);
摘要功能removeunit(单位为单位);
摘要bombardstrength()函数;
}
级部队扩充部队单位
私有$单位=数组();
功能addunit(单位美金){
如果(in_array(美元单位,美元->单位,true){ / /美元)用于调用正常的属性或方法,调用静态属性自我的方法,或常数。
返回;
}
$这个单位{ } = $单位;
}
功能removeunit(单位美金){
5.3
美元->单位= array_udiff(美元->单元阵列(美金),
功能($,$)收益($ = $){ 0:1 });
< 5.3
/ /美元->单位= array_udiff(美元->单元阵列(美金),
/ / create_function($,$',返回($ = $ B)0:1;'));
/ / create_function,创建对象数组,函数
}
功能bombardstrength(){
0美元;
foreach(美元->单位为美元单位){
($ ret = $单位-> bombardstrength);
}
返回$;
}
}
示例类
类坦克扩展单元
功能addunit(单位美金){ }
功能removeunit(单位美金){ }
功能bombardstrength(){
返回4;
}
}
类兵扩展单位{士兵
功能addunit(单位美金){ }
功能removeunit(单位美金){ }
功能bombardstrength(){
返回8;
}
}
坦克=新坦克();
TANK2 =新的坦克(美元);
士兵=新兵();
陆军=新军();
军> addunit美元(合兵);
军> addunit美元($罐);
军> addunit美元(约合TANK2);
print_r(元军);
印军-> bombardstrength(美元)。;
军> removeunit美元(合兵);
print_r(元军);
印军-> bombardstrength(美元)。;
>




输出:


军队的对象

{单位:军队:私人} =数组

{ 0 }战士对象


{ 1个}坦克对象


{ 2个}坦克对象




十六
军队的对象

{单位:军队:私人} =数组

{ 1个}坦克对象


{ 2个}坦克对象









添加异常处理


< PHP
抽象类单元{
摘要功能addunit(单位为单位);
摘要功能removeunit(单位为单位);
摘要bombardstrength()函数;
}
阶级军队扩展单位{
私有$单位=数组();
功能addunit(单位美金){
如果(in_array(美元单位,美元->单位,真)){
返回;
}
$这个单位{ } = $单位;
}
功能removeunit(单位美金){
5.3
/ /美元->单位= array_udiff(美元->单元阵列(美金),
/ /功能($,$)收益($ = $){ 0:1 });
< 5.3
美元->单位= array_udiff(美元->单元阵列(美金),
create_function($,$',返回($ = $ B)0:1;'));
}
功能bombardstrength(){
0美元;
foreach(美元->单位为美元单位){
($ ret = $单位-> bombardstrength);
}
返回$;
}
}
类unitexception延伸例外{ }
类弓箭手扩展单位{
功能addunit(单位美金){
把新的unitexception(get_class(美元)。是一个叶子);
}
功能removeunit(单位美金){
把新的unitexception(get_class(美元)。是一个叶子);
}
功能bombardstrength(){
返回4;
}
}
弓箭手=新弓箭手();
archer2美元=新射手();
射手- > addunit美元(美元archer2);
>




输出:

致命错误:未捕获的exception'unitexception'with message'archer是叶

注释:组合模式中的所有类共享相同的父类型,因此在设计中很容易添加新的复合对象或本地对象,而不需要在大范围内修改代码。

最终效果,逐步优化(完美):


< PHP
类unitexception延伸例外{ }
抽象类单元{
摘要bombardstrength()函数;
功能addunit(单位美金){
把新的unitexception(get_class(美元)。是一个叶子);
}
功能removeunit(单位美金){
把新的unitexception(get_class(美元)。是一个叶子);
}
}
类弓箭手扩展单位{
功能bombardstrength(){
返回4;
}
}
类lasercannonunit扩展单元{
功能bombardstrength(){
返回44;
}
}
阶级军队扩展单位{
私有$单位=数组();
功能addunit(单位美金){
如果(in_array(美元单位,美元->单位,真)){
返回;
}
$这个单位{ } = $单位;
}
功能removeunit(单位美金){
5.3
/ /美元->单位= array_udiff(美元->单元阵列(美金),
/ /功能($,$)收益($ = $){ 0:1 });
< 5.3
美元->单位= array_udiff(美元->单元阵列(美金),
create_function($,$',返回($ = $ B)0:1;'));
}
功能bombardstrength(){
0美元;
foreach(美元->单位为美元单位){
($ ret = $单位-> bombardstrength);
}
返回$;
}
}
军队{创造}
main_army美元=新的军队();
某些单位
main_army美元-> addunit(New Archer());
main_army美元-> addunit(新lasercannonunit());
新的军队{创造}
sub_army美元=新的军队();
某些单位
sub_army美元-> addunit(New Archer());
sub_army美元-> addunit(New Archer());
sub_army美元-> addunit(New Archer());
将第二军团加入到第一
main_army -> addunit美元(美元sub_army);
所有的计算都在后台处理。
打印攻击强度:{ $ main_army -> bombardstrength()()} ;
>




输出:

以力量攻击:60

更逼合,


< PHP
抽象类单元{
功能getcomposite(){
返回null;
}
摘要bombardstrength()函数;
}
抽象类compositeunit扩展单元{ / /类的抽象类
私有$单位=数组();
功能getcomposite(){
返回$此;
}
受保护函数单元(){
返回$这个单位;
}
功能removeunit(单位美金){
5.3
/ /美元->单位= array_udiff(美元->单元阵列(美金),
/ /功能($,$)收益($ = $){ 0:1 });
< 5.3
美元->单位= array_udiff(美元->单元阵列(美金),
create_function($,$',返回($ = $ B)0:1;'));
}
功能addunit(单位美金){
如果(in_array(美元单位,美元->单位,真)){
返回;
}
$这个单位{ } = $单位;
}
}
班军延伸compositeunit {
功能bombardstrength(){
0美元;
foreach(美元->单位为美元单位){
($ ret = $单位-> bombardstrength);
}
返回$;
}
}
类弓箭手扩展单位{
功能bombardstrength(){
返回4;
}
}
类lasercannonunit扩展单元{
功能bombardstrength(){
返回44;
}
}
类unitscript {
静态函数joinexisting(单位为newunit,
单位occupyingunit美元){ / /静态方法,直接通过类来使用
为补偿;
如果(!is_null($ COMP)=($ occupyingunit -> getcomposite)){ / /军队整顿
计算机> addunit美元(美元newunit);
}其他士兵的综合治疗
新陆军();
计算机> addunit美元(美元occupyingunit);
计算机> addunit美元(美元newunit);
}
返回$;
}
}
army1美元=新的军队();
army1美元-> addunit(New Archer());
army1美元-> addunit(New Archer());
陆军2美元=新的军队();
陆军2美元-> addunit(New Archer());
陆军2美元-> addunit(New Archer());
陆军2美元-> addunit(新lasercannonunit());
复合= unitscript::joinexisting美元($陆军2,army1美元);
print_r($复合);
>




输出:


军队的对象

{单位:compositeunit:私人} = >阵列

{ 0


{ 1


{陆军对象2

{单位:compositeunit:私人} = >阵列

{ 0


{ 1


{ 2 } = > lasercannonunit对象










点评:该装置的基础上,对compositeunit复合实现添加和删除。军队继承复合,而射手继承射手。这样,就不会有额外的添加和删除在射击方法。

装饰图案

装饰图案有助于我们改变特定成分的功能。

请看例子


< PHP
抽象类平铺
摘要功能(getwealthfactor); / /获得财富
}
类平原扩展平铺
私人wealthfactor = 2美元;
功能getwealthfactor(){
返回wealthfactor美元->;
}
}
类diamondplains延伸平原{ / /钻石地段
功能getwealthfactor(){
返回父::getwealthfactor()+ 2;
}
}
类pollutedplains延伸平原{ / /污染区
功能getwealthfactor(){
返回:getwealthfactor母:()- 4;
}
}
瓦=新pollutedplains(美元);
打印$瓦-> getwealthfactor();
>




输出:

- 2

点评:没有灵活性,我们无法同时获得钻石和污染土地的资本。

装饰模式使用组合和代表团,而不是只使用继承来解决功能变化的问题。

看看例子:


< PHP
抽象类{ {
摘要getwealthfactor()函数;
}
类平原扩展瓦片{
私人wealthfactor = 2美元;
功能getwealthfactor(){
返回wealthfactor美元->;
}
}
抽象类tiledecorator延伸瓦{ / /装饰
受保护的瓷砖;
功能__construct(瓷砖瓷砖美元){
此$;
}
}
类diamonddecorator延伸tiledecorator { / /钻石。
功能getwealthfactor(){
返回这个->瓦-> getwealthfactor()+ 2;
}
}
类pollutiondecorator延伸tiledecorator { / /装修污染
功能getwealthfactor(){
返回这个->瓦-> getwealthfactor()- 4;
}
}
新普莱恩斯();
打印(合瓦-> getwealthfactor); / / 2
瓦=新diamonddecorator美元(新平原());
打印(合瓦-> getwealthfactor); / / 4
PollutionDecorator(新瓦=美元
新的diamonddecorator(新平原())))
打印(合瓦-> getwealthfactor); / / 0
>




输出:







点评:该模型具有可扩展性。我们不需要创造一个diamondpollutionplains对象建立一个污染对象的钻石。

一个更现实的例子


< PHP
Class RequestHelper{} / / Assistant request
抽象类的ProcessRequest { / /工艺要求
抽象函数的过程(requesthelper $ REQ);
}
类主要{ / /扩展接口的主进程
函数过程(requesthelper $ REQ){
打印__class__。用请求做一些有用的事情;
}
}
抽象类decorateprocess ProcessRequest { / /延伸的装饰工艺
保护$接口;
功能__construct(ProcessRequest $ PR){ / /参考对象,委托
美元-> ProcessRequest = $公关;
}
}
类logrequest延伸decorateprocess { / /日志请求
函数过程(requesthelper $ REQ){
打印__class__。日志记录请求/当前类,递归的感觉
美元-> ProcessRequest ->过程(合要求);
}
}
课堂延伸decorateprocess AuthenticateRequest { / /认证要求
函数过程(requesthelper $ REQ){
打印__class__。:验证请求;
美元-> ProcessRequest ->过程(合要求);
}
}
类structurerequest延伸decorateprocess { / /组织的要求
函数过程(requesthelper $ REQ){
打印__class__。结构化请求;
美元-> ProcessRequest ->过程(合要求);
}
}
$过程=新AuthenticateRequest(新structurerequest)
新的logrequest(
新公路()
))这个关系可以合并,过程非常灵活,消除了许多重复的继承。
$过程->过程(New RequestHelper());
print_r(合过程);
>




输出:


AuthenticateRequest:认证要求
StructureRequest:结构要求
logrequest:登录请求
主要工艺:做点有用的请求
AuthenticateRequest对象

{ } = > structurerequest ProcessRequest:保护对象

{ } = > logrequest ProcessRequest:保护对象

{ } = > ProcessRequest:保护的主要对象









评论:有递归的感觉,一层一层,由牛总结出来,灵活地解决一些实际问题!多发展一点想法。

更多有关PHP相关内容的感兴趣的读者可以查看主题:PHP面向对象编程教程

希望本文能对PHP程序设计有所帮助。