首页 > php教程 > php手册 > 正文

返璞归真:PHP中面向过程的装饰模式实现

WBOY
发布: 2016-06-06 19:40:26
原创
877 人浏览过

本文可以看做是Web框架审美观一文的延续,在那篇文章里,我阐述了如何用 面向 对象 实现 装饰 模式 ,不过鉴于PHP的本质就是 面向 过程 的,让我对纯粹的OOP有些拿不定主意,于是本文便走向另一个极端,准备阐述一下如何用 面向 过程 实现 装饰 模式 。 废话

  本文可以看做是Web框架审美观一文的延续,在那篇文章里,我阐述了如何用面向对象实现装饰模式,不过鉴于PHP的本质就是面向过程的,让我对纯粹的OOP有些拿不定主意,于是本文便走向另一个极端,准备阐述一下如何用面向过程实现装饰模式

  废话少说,直接贴代码(代码仅在PHP5.3以上版本有效,用到了header_remove函数),大概涉及以下几个文件:

<p><span>bootstrap</span><span>.</span><span>php:<br><br></span><span>01</span><span>function</span><span> execute_action(</span><span>$name</span><span>=</span><span>null</span><span>)<br></span><span>02</span><span> {<br></span><span>03</span><span>static</span><span>$action</span><span>;<br></span><span>04</span><span>static</span><span>$wrappers</span><span>;<br></span><span>05</span><span><br></span><span>06</span><span>if</span><span> (</span><span>$name</span><span>!==</span><span>null</span><span>) {<br></span><span>07</span><span>$action</span><span>=</span><span>$name</span><span>;<br></span><span>08</span><span>     }<br></span><span>09</span><span><br></span><span>10</span><span>if</span><span> (</span><span>$wrappers</span><span>===</span><span>null</span><span>) {<br></span><span>11</span><span>$config</span><span>=</span><span>include</span><span>'</span><span>config.php</span><span>'</span><span>;<br></span><span>12</span><span>$wrappers</span><span>=</span><span>$config</span><span>[</span><span>$action</span><span>];<br></span><span>13</span><span>     }<br></span><span>14</span><span><br></span><span>15</span><span>if</span><span> (</span><span>list</span><span>(</span><span>$wrapper</span><span>,</span><span>$param</span><span>) </span><span>=</span><span>each</span><span>(</span><span>$wrappers</span><span>)) {<br></span><span>16</span><span>extract</span><span>(</span><span>$param</span><span>);<br></span><span>17</span><span>array_shift</span><span>(</span><span>$wrappers</span><span>);<br></span><span>18</span><span><br></span><span>19</span><span>return</span><span>include</span><span>$wrapper</span><span>.</span><span>'</span><span>_wrapper.php</span><span>'</span><span>;<br></span><span>20</span><span>     }<br></span><span>21</span><span><br></span><span>22</span><span>ob_start</span><span>();<br></span><span>23</span><span><br></span><span>24</span><span>include</span><span>$action</span><span>.</span><span>'</span><span>_action.php</span><span>'</span><span>;<br></span><span>25</span><span><br></span><span>26</span><span>return</span><span>ob_get_clean</span><span>();<br></span><span>27</span><span> }<br></span><span>28</span><span><br></span><span>29</span><span>echo</span><span> execute_action(</span><span>'</span><span>foo</span><span>'</span><span>);</span></p>
登录后复制

  说明:这里的static变量是面向过程装饰模式实现关键,它会控制程序依次执行所有的装饰器和动作。

<p><span>config</span><span>.</span><span>php:<br><br></span><span>01</span><span>return</span><span>array</span><span>(<br></span><span>02</span><span>'</span><span>foo</span><span>'</span><span>=></span><span>array</span><span>(<br></span><span>03</span><span>'</span><span>bar</span><span>'</span><span>=></span><span>array</span><span>(</span><span>'</span><span>param_a</span><span>'</span><span>=></span><span>'</span><span>[a]</span><span>'</span><span>,</span><span>'</span><span>param_b</span><span>'</span><span>=></span><span>'</span><span>[b]</span><span>'</span><span>)</span><span>,</span><span><br></span><span>04</span><span>//</span><span> other wrappers</span><span><br></span><span>05</span><span>     )</span><span>,</span><span><br></span><span>06</span><span>//</span><span> other actions</span><span><br></span><span>07</span><span> );</span></p>
登录后复制

  说明:配置文件使用的是直接return的方式,在include的时候可以接收到参数,里面可以针对动作设置装饰器,并且可以设置装饰器的参数。

<p><span>bar_wrapper</span><span>.</span><span>php:<br><br></span><span>01</span><span>$result</span><span>=</span><span> execute_action();<br></span><span>02</span><span><br></span><span>03</span><span> header_remove(</span><span>'</span><span>Location</span><span>'</span><span>);<br></span><span>04</span><span><br></span><span>05</span><span>return</span><span>$result</span><span>.</span><span>$param_a</span><span>.</span><span>$param_b</span><span>;</span></p>
登录后复制

  说明:在装饰器里可以修改响应头,还可以修改响应内容,注意结果是return的,不是echo的。

<p><span>foo_action</span><span>.</span><span>php:<br><br></span><span>01</span><span>header</span><span>(</span><span>'</span><span>Location: http://www.baidu.com/</span><span>'</span><span>);<br></span><span>02</span><span>//</span><span> exit; or return;</span><span><br></span><span>03</span><span><br></span><span>04</span><span>echo</span><span>'</span><span>hello, world.</span><span>'</span><span>;</span></p>
登录后复制

  说明:在动作里没有任何特殊性,就是页面控制器风格,这样可以兼容最一般的PHP编程风格。

  把以上文件保存到根目录,然后浏览bootstrap.php就可以看到效果:hello, world.[a][b]。全部代码都是面向过程的,和面向对象不沾边,对PHP这样的瞬态执行的语言来说,这样可以实现效率最大化。再看细节,虽然我们在动作文件里设定了跳转,但是在装饰器文件里可以删除这个响应头,从而达到透明修改的装饰目的,装饰器对动作的修改没有任何侵入性设计。以此为基础,可以实现一个相当灵活的Web框架(VC of MVC),既能保证效率,又可以兼顾扩展性。不过这样的设计也有一些弱点,比如说可测试性会有点麻烦,另外,没有了OOP,显得有些土气(如果你这样认为的话)。

  注意:由于在操作action和wrapper的时候,使用的是include方式,所以可能会带来变量污染的问题,一般来说,只要稍加注意不会出大问题,不过如果有完美主义倾向,可以使用PHP5.3新加入的闭包特色来规避这类问题:function() use(...) { include ... };,但效率会略微降低一点。

  补充:肯定会有人鄙视这样的面向过程风格的代码,其实大可不必,我记得以前有好事者曾经问过CPP之父一个尖锐的问题:和Ruby这样百分百面向对象的语言相比,CPP是不是显得不够好?CPP之父回答道:我不认为百分百面向对象是优点!对于PHP来说,我也认为百分百面向对象不可取,当然百分百面向过程也不可取,在我看来更合理的方式是:如果按MVC算的话,M应该是面向对象的,而VC则应该是面向过程的,这样可以达到一个合理的平衡点。

相关标签:
来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门推荐
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板