Day44. 范例:文字积木 (蝇量模式)

本文同步更新於blog

情境:这是公司生产的文字积木

<?php

namespace App\Flyweight\Blocks;

class ConcreteBlock
{
    /**
     * @var string
     */
    protected $shape;

    /**
     * @var string
     */
    public $word;

    /**
     * @param string $shape
     * @param string $word
     */
    public function __construct(string $shape, string $word)
    {
        $this->shape = $shape;
        $this->word = $word;
    }

    /**
     * @return string
     */
    public function getShape(): string
    {
        return $this->shape;
    }

    /**
     * @return string
     */
    public function getWord(): string
    {
        return $this->word;
    }
}

  • 客户端的使用方式
namespace App\Flyweight\Blocks;
<?php

namespace App\Flyweight\Blocks;

use App\Flyweight\Blocks\ConcreteBlock;

class Program
{
    /**
     * @return array
     */
    public function getBlocks(): array
    {
        $firstBlock = new ConcreteBlock('star', 'B');
        $secondBlock = new ConcreteBlock('square', 'E');
        $thirdBlock = new ConcreteBlock('square', 'A');
        $fourthBlock = new ConcreteBlock('square', 'R');

        return [$firstBlock, $secondBlock, $thirdBlock, $fourthBlock];
    }
}

随着积木越卖越好,我们会创建出许多Block,
它们要显示的文字各不相同,但形状大概就那几种。

我们决定改变积木的实作,不纪录显示文字於积木的状态中
抽离出共用的形状部分,来节省记忆体的消耗。


  • 首先定义抽象的积木介面
<?php

namespace App\Flyweight\Blocks\Contracts;

interface Block
{
    public function getShape();
    public function display(string $word): string;
}

之後我们要显示文字时,会使用display()方法。


  • 接着定义实体积木
<?php

namespace App\Flyweight\Blocks;

use App\Flyweight\Blocks\Contracts\Block;

class ConcreteBlock implements Block
{
    /**
     * @var string
     */
    protected $shape;

    /**
     * @param string $shape
     */
    public function __construct(string $shape)
    {
        $this->shape = $shape;
    }

    /**
     * @return string
     */
    public function getShape(): string
    {
        return $this->shape;
    }

    /**
     * @param string $word
     * @return string
     */
    public function display(string $word): string
    {
        return $word;
    }
}

<?php

namespace App\Flyweight\Blocks;

use App\Flyweight\Blocks\ConcreteBlock;
use App\Flyweight\Blocks\Contracts\Block;

class BlockFactory
{
    /**
     * @var Block[]
     */
    protected $blocks;

    /**
     * @param string $shape
     * @return ConcreteBlock
     */
    public function getBlock(string $shape): Block
    {
        if (!isset($this->blocks[$shape])) {
            $this->blocks[$shape] = new ConcreteBlock($shape);
        }

        return $this->blocks[$shape];
    }
}

  • 最後修改客户端的使用方式
<?php

namespace App\Flyweight\Blocks;

use App\Flyweight\Blocks\Block;

class Program
{
    /**
     * @return array
     */
    public function getBlocks(): array
    {
        $blockFactory = new BlockFactory();

        $firstBlock = $blockFactory->getBlock('star');
        // $firstBlock->display('B');

        $secondBlock = $blockFactory->getBlock('square');
        // $secondBlock->display('E');

        $thirdBlock = $blockFactory->getBlock('square');
        // $thirdBlock->display('A');

        $fourthBlock = $blockFactory->getBlock('square');
        // $fourthBlock->display('R');

        return [$firstBlock, $secondBlock, $thirdBlock, $fourthBlock];
    }
}

当客户端要显示文字时,再呼叫display()方法。


[单一职责原则]
我们将管理内部状态管理外部状态,视为两种不同的职责。

透过区分两者,我们便可以用 简单工厂模式 搭配 单例模式
切出细粒度的物件,来共用相同的程序码。

其蝇量类别只纪录内部状态且创建後便不会改变。

[开放封闭原则]
透过工厂,我们可以修改积木本身的实作(例如换厂牌),而不影响客户端。
当客户端修改外部状态时,也不影响原本纯内部状态的积木。

[里氏替换原则]
工厂依赖於抽象的积木介面。
实体积木实作了抽象的积木介面。

最後附上类别图:
https://ithelp.ithome.com.tw/upload/images/20201127/20111630HZxVHEhR1n.png
(注:若不熟悉 UML 类别图,可参考UML类别图说明。)

ʕ •ᴥ•ʔ:原来共享经济是用了蝇量模式的概念啊。


<<:  虚拟主机是什麽又该如何选择?2020 最新台湾虚拟主机推荐比较

>>:  如何在Windows 10中启用或禁用系统保留存储

DAY15 服务室--JSON Server自己开

前言 我们现在有了 Nuxt.js 建立的环境、有了 Vuex 来做资料的处理,现在就差资料要从哪里...

Day09 - 语音特徵正规化

当一个模型的训练资料和测试资料,彼此之间的资料分布有不匹配(mismatch)时,模 型的性能会出现...

离职倒数29天:远端道别

 开始上班後,从来没放过这麽长的假,而且还没出门旅行。给自己的每天的例行功课就是看书跟写日记,昨天把...

【Day 02】战略资讯系统(Strategic information system)

战略资讯系统 中台架构其实是一种整体资讯架构订定的思维,其目的是为了迎接企业不断创新的挑战,在『变是...

[Day 30] Tips for Lazy Loading Images

Lazy loading 是广为人知的网页优化技巧,尤其应用在图片上时能够大幅减少效能和流量的浪费,...