Whip Monstrous Code Into Shape 13-Consider Decorating

The next option you have when cleaning up monstrous code is opting for decorators. This allows you to stack on behavior to an existing class dynamically. I'll show you how; it's easy!


这个视频介绍的是使用装饰(Decorating)来优化清理代码。

装饰模式(Decorator)是一种动态的往一个类中添加新的功能的设计模式,关于装饰模式,我觉得这个文章写的挺详细的,可以看看。

我在学设计模式的时候一直有个困惑,这些设计模式都能理解,但是不知道如何运用到开发中。通常介绍设计模式的文章都有一个很基本的结构图,于是出现这种情况:开发的时候碰到某些情形,看起来使用某种开发模式会比较合适,于是本能的拿设计模式的结构图跟实际情况套,到最后发现有差异,于是放弃使用这种设计模式。现在想想,可能是没有真正的理解设计模式的意图,而是简单的按照某种结构套。

比如装饰模式,通常是用在一些系统中有大量独立的扩展的情况,但是本质是在不破坏类的情况下动态的添加一些新的功能,下面的例子就是一个简单的应用。

想象有种情形,发表一篇文章,我们创建了一个 ArticlePublish 服务,在控制器中调用这个服务的 publish 方法。

class ArticlesController extends Controller
{
    public function store()
    {
        $article = new ArticlePublish();

        $article->publish();
    }
}

class ArticlePublish
{
    public function publish()
    {
        var_dump('store db and publish');
    }
}

可能过段时间想加个功能,某些精华文章自己还希望在发表完成后可以同步到微博中。我之前的做法可能就是在 ArticlePublish 中加一个判断。

class ArticlePublish
{
    public function publish()
    {
        var_dump('store db and publish');

        if (...) {
            var_dump('publish on weibo...');
        }
    }
}

这种情况下可以考虑使用装饰(Decorating),我们的目的就是在不破坏 ArticlePublish 本身的功能基础上动态的增加一些新的功能。装饰器通常和被装饰的对象是同一种类型,有一个相同的方法,通过先调用被装饰对象的方法再加自己本身的处理逻辑来添加功能。

创建一个装饰器,ArticlePublishWeibo (不要在意名字...)。

class ArticlePublishWeibo
{
    /**
     * @var ArticlePublish
     */
    private $article;

    public function __construct(ArticlePublish $article)
    {

        $this->article = $article;
    }

    public function publish()
    {
        $this->article->publish();

        var_dump('publish on weibo');
    }
}

可以看到,通过创建一个装饰器,把被装饰对象包裹起来,一方面通过代理调用被装饰的对象,一方面添加新的功能。控制器中的调用:

class ArticlesController extends Controller
{
    public function store()
    {
        //$article = new ArticlePublish();

        $article = new ArticlePublishWeibo(new ArticlePublish());

        $article->publish();
    }
}

如果还需要添加新的功能,只需要创建一个新的装饰器,把 ArticlePublishWeibo 包裹起来,添加一个同名方法,就可以添加新的功能。

从这个例子可以看到,我们在使用设计模式的时候没有必要一味按照设计模式的一些结构来组织自己的逻辑关系,而是真正使用设计模式的精髓。

当然这个方法也有些弊端,比如随着功能增多会产生很多小对象,增加系统复杂度,加大学习与理解的难度等等。没有必要到处使用,只是多一些选择,某种情况下会有很好的效果。

本帖已被设为精华帖!
本帖由 Summer 于 7年前 加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!