前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Web框架与太阳系

Web框架与太阳系

作者头像
LA0WAN9
发布2021-12-14 08:22:52
5400
发布2021-12-14 08:22:52
举报
文章被收录于专栏:火丁笔记

古语有云:工欲善其事,必先利其器。对于Web开发亦是如此,不过现在的Web框架实在是太多了!以PHP为例,有CakePHPCodeIgniterSymfonyZendYii等等,到底谁是最合适的?事实上过多的选择往往会让人陷入「乱花渐欲迷人眼」的窘境,这些年我一直游走在各种PHP框架之间,却始终没有觅得属于自己的屠龙刀,于是我决定自己动手,就像歌里唱的那样:不是你亲手点燃的那就不能叫做火焰。

既然要自己动手,那么就需要明确一下设计目标,我个人主要关注以下几个方面:微内核、模块化、扩展性。套用陈道明说过的一句广告语:简约而不简单。

在说明设计方案之前,不妨放松一下心情,聊聊看似风马牛不相及的太阳系:

Solar System

在我小时候,课本上教的是太阳系有九大行星,分别是:水星、金星、地球、火星、木星、土星、天王星、海王星和冥王星。其中,冥王星较小,后来,人们发现还有一些和冥王星类似的天体也在围绕太阳运转,如果冥王星被划为行星的话,那么这些天体无疑也属于行星,此时太阳系到底有几大行星的问题彻底让天文学家蒙圈了,最后他们耍了一个小聪明,剥夺冥王星的行星资格就行了,从此太阳系就只剩八大行星了。

当然,我并不是让你关注这些天文学上的八卦往事,实际上我希望你关注的是太阳系的结构模式:有的行星是丁克家庭,没有卫星,比如水星和金星;有的行星是计划生育标兵,比如地球只有一个卫星(月亮);有的行星是超生游击队,卫星多的数不胜数,以至于起名时只能以阿拉伯数字加以区分,比如木星和土星。卫星沿着自己的轨道围绕着行星旋转,行星沿着自己的轨道围绕着太阳旋转,这就是太阳系!

如果你了解设计模式的话,那么你会惊讶的发现,上帝是一个设计模式大师,他在设计宇宙的结构时,使用了装饰器模式:月亮装饰着地球,地球装饰着太阳,甚至太阳系本身也是银河系的一个装饰器,如此循环,这就是宇宙!

既然上帝只用了装饰器这一个概念便创造了整个世界,那么我们能不能利用装饰器模式创造Web框架呢?实际上类似的框架在Python社区中早就有了,可惜PHP社区却好像始终无动于衷,我在几年前做过一些粗浅的尝试,但是由于种种原因搁置了,最近借着公司一个项目的改版,我终于完成了它,并命名为「Beahoo」,它是一个迷你框架,代码极简,很好的诠释了我前面提的目标:微内核、模块化、扩展性。

我们先来看看控制器中Action的代码实现:

代码语言:javascript
复制
<?php

namespace Beahoo\Controller;

abstract class Action
{
    protected $decorators = array();

    public function build(Action $action = null)
    {
        if ($action === null) {
            $action = $this;
        }

        $decorators = array();

        for (
            $class = get_class($action);
            $vars  = get_class_vars($class);
            $class = get_parent_class($class)) {

            if (empty($vars['decorators'])) {
                continue;
            }

            foreach ($vars['decorators'] as $decorator => $name) {
                if (is_int($decorator)) {
                    list($decorator, $name) = array($name, null);
                }

                if (!isset($decorators[$decorator])) {
                    $decorators[$decorator] = $name;
                }
            }
        }

        $core = $action;

        $decorators = array_reverse($decorators);

        foreach ($decorators as $decorator => $name) {
            if ($name === false) {
                continue;
            }

            $decorator = $this->load($decorator, $action);
            $action = $this->build($decorator);

            if ($name) {
                $core->{$name} = $decorator;
            }
        }

        return $action;
    }

    protected function load($class, $args = null)
    {
        if ($args === null) {
            return new $class;
        }

        if (!is_array($args)) {
            $args = array($args);
        }

        $reflection = new \ReflectionClass($class);

        return $reflection->newInstanceArgs($args);
    }

    abstract public function execute(
        Request $request,
        Response $response
    );
}

我们再来看看控制器中Decorator的代码实现:

代码语言:javascript
复制
<?php

namespace Beahoo\Controller;

abstract class Decorator extends Action
{
    protected $action;

    public function __construct(Action $action)
    {
        $this->action = $action;
    }

    public function getNextAction()
    {
        return $this->action;
    }

    public function getLastAction()
    {
        $action = $this->action;

        while (is_subclass_of($action, __CLASS__)) {
            $action = $action->action;
        }

        return $action;
    }

    public function execute(Request $request, Response $response)
    {
        $this->action->execute($request, $response);
    }
}

本文省略了细枝末节的代码实现,只保留了最关键的Action和Decorator,几百行代码就实现了DNA双螺旋结构,只要有了它们,便可以衍生出丰富多彩的生命形式。

让我们扮演一把上帝,看看如何利用装饰器模式创建太阳系:

代码语言:javascript
复制
<?php

namespace SolarSystem\Controller\Action;

use Beahoo\Controller\Request;
use Beahoo\Controller\Response;

class SunAction extends \Beahoo\Controller\Action
{
    protected $decorators = array(
        'SolarSystem\Controller\Decorator\NeptuneDecorator',
        'SolarSystem\Controller\Decorator\UranusDecorator',
        'SolarSystem\Controller\Decorator\SaturnDecorator',
        'SolarSystem\Controller\Decorator\JupiterDecorator',
        'SolarSystem\Controller\Decorator\MarsDecorator',
        'SolarSystem\Controller\Decorator\EarthDecorator',
        'SolarSystem\Controller\Decorator\VenusDecorator',
        'SolarSystem\Controller\Decorator\MercuryDecorator',
    );

    public function execute(Request $request, Response $response)
    {
        // ...
    }
}

装饰器本身也可以被装饰器装饰,比如地球和月球的关系就是个极好的例子:

代码语言:javascript
复制
<?php

namespace SolarSystem\Controller\Decorator;

use Beahoo\Controller\Request;
use Beahoo\Controller\Response;

class EarthDecorator extends \Beahoo\Controller\Decorator
{
    protected $decorators = array(
        'SolarSystem\Controller\Decorator\Earth\MoonDecorator',
    );

    public function execute(Request $request, Response $response)
    {
        // ...
    }
}

怎么样?是不是有种造物主的成就感,太阳系就在我们手中,设想一下:如果有一颗彗星正在穿越太阳系会发生什么情景,那么就让我们运行它试试吧:

代码语言:javascript
复制
<?php

$sun = new \SolarSystem\Controller\Action\SunAction;
$sun->build()->execute($request, $response);

虽然本框架在代码实现上秉承了极简的原则,但是在功能上却毫不逊色,篇幅所限,我无法一一说明,有兴趣的读者不妨自己探索一下吧。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2014-06-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档