天天看點

php中享元模式

概念

享元模式(Flyweight),為了節約記憶體的使用,享元模式會盡量使類似的對象共享記憶體。在大量類似對象被使用的情況中這是十分必要的。常用做法是在外部資料結構中儲存類似對象的狀态,并在需要時将他們傳遞給享元對象

示例

<?php

/**
 * 建立享元接口 FlyweightInterface 。
 */
interface FlyweightInterface
{

   /**
    * 建立傳遞函數。
    * 傳回字元串格式資料。
    */
    public function render(string $extrinsicState): string;
}


/**
 * 假如可以的話,實作享元接口并增加記憶體存儲内部狀态。
 * 具體的享元執行個體被工廠類的方法共享。
 */
class CharacterFlyweight implements FlyweightInterface
{
    /**
     * 任何具體的享元對象存儲的狀态必須獨立于其運作環境。
     * 享元對象呈現的特點,往往就是對應的編碼的特點。
     *
     * @var string
     */
    private $name;

    /**
     * 輸入一個字元串對象 $name。
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }

    /**
     * 實作 FlyweightInterface 中的傳遞方法 render() 。
     */
    public function render(string $font): string
    {
         // 享元對象需要用戶端提供環境依賴資訊來自我定制。
         // 外在狀态經常包含享元對象呈現的特點,例如字元。

        return sprintf('Character %s with font %s', $this->name, $font);
    }
}


/**
 * 工廠類會管理分享享元類,用戶端不應該直接将他們執行個體化。
 * 但可以讓工廠類負責傳回現有的對象或建立新的對象。
 */
class FlyweightFactory implements \Countable
{
    /**
     * @var CharacterFlyweight[]
     * 定義享元特征數組。
     * 用于存儲不同的享元特征。
     */
    private $pool = [];

    /**
     * 輸入字元串格式資料 $name。
     * 傳回 CharacterFlyweight 對象。
     */
    public function get(string $name): CharacterFlyweight
    {
        if (!isset($this->pool[$name])) {
            $this->pool[$name] = new CharacterFlyweight($name);
        }

        return $this->pool[$name];
    }

    /**
     * 傳回享元特征個數。
     */
    public function count(): int
    {
        return count($this->pool);
    }
}



/**
 * 建立測試單元 FlyweightTest 。
 */
class FlyweightTest
{
    private $characters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
        'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    private $fonts = ['Arial', 'Times New Roman', 'Verdana', 'Helvetica'];

    public function testFlyweight()
    {
        $factory = new FlyweightFactory();

        foreach ($this->characters as $char) {
            foreach ($this->fonts as $font) {
                $flyweight = $factory->get($char);
                $rendered = $flyweight->render($font);
            }
        }

        // 享元模式會保證執行個體被分享。
        // 相比擁有成百上千的私有對象,
        // 必須要有一個執行個體代表所有被重複使用來顯示不同單詞的字元。
    }
}