php设计模式(十六)享元模式

享元模式的目的是为了减少实例化大量的类时对内存的占用;
减少是不可能平白无故就减少了的;
主要是通过复用重复的类来实现;
用现在比较热的词叫共享;
就比如说现实生活中;
我们有 99 件尺寸为 L 和 1 件 XXL 的不同款式的男装需要请多少个模特?
回答 100 的同学肯定是家里有矿了;
省钱的方案是只请2个模特就够了;
其中 99 件 L 的需要一个 170cm 的模特;
剩下的 1 件 XXL 的需要 180cm 的模特;
咱们用代码来演示下;

结构

Flyweight: 享元抽象类
ConcreteFlyweight:实现 Flyweight 接口的可以共享的具体享元类
UnsharedConcreteFlyweight: 非共享具体享元类
FlyweightFactory: 用于创建和管理具体的享元对象的工厂;

示例

Flyweight.php

<?php

namespace Baijunyao\DesignPatterns\Flyweight;

/**
 * 享元抽象类
 *
 * Class Flyweight
 *
 * @package Baijunyao\DesignPatterns\Flyweight
 */
abstract class Flyweight
{
    /**
     * @var
     */
    protected $name;

    /**
     * Flyweight constructor.
     *
     * @param $name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * @param $content
     */
    public function show($content){}
}

ConcreteFlyweight.php

<?php

namespace Baijunyao\DesignPatterns\Flyweight;

/**
 * 共享的具体享元类
 *
 * Class ConcreteFlyweight
 *
 * @package Baijunyao\DesignPatterns\Flyweight
 */
class ConcreteFlyweight extends Flyweight
{
    /**
     * @param $content
     */
    public function show($content)
    {
        echo '共享的享元:' . $this->name . $content . '<br>';
    }
}

UnsharedConcreteFlyweight.php

<?php

namespace Baijunyao\DesignPatterns\Flyweight;

/**
 * 不共享的具体享元类
 *
 * Class UnsharedConcreteFlyweight
 *
 * @package Baijunyao\DesignPatterns\Flyweight
 */
class UnsharedConcreteFlyweight extends Flyweight
{
    /**
     * @param $content
     */
    public function show($content)
    {
        echo '不共享的享元:' . $this->name . $content . '<br>';
    }

    /**
     * 附加的删除方法
     */
    public function delete()
    {
        $this->name = '';
    }
}

FlyweightFactory.php

<?php

namespace Baijunyao\DesignPatterns\Flyweight;

/**
 * 享元工厂
 *
 * Class FlyweightFactory
 *
 * @package Baijunyao\DesignPatterns\Flyweight
 */
class FlyweightFactory
{
    /**
     * @var array
     */
    private $flyweights = [];

    /**
     * @param $name
     *
     * @return mixed
     */
    public function getFlyweight($name)
    {
        if(!isset($this->flyweights[$name])){
            $this->flyweights[$name]=new ConcreteFlyweight($name);
        }
        return $this->flyweights[$name];
    }
}

运行;
index.php

<?php

namespace Baijunyao\DesignPatterns\Flyweight;

require __DIR__.'/../vendor/autoload.php';

/**
 * 客户端
 *
 * Class Client
 * @package Baijunyao\DesignPatterns\Flyweight
 */
class Client
{
    /**
     * 运行
     */
    public function run()
    {
        $flyweight = new FlyweightFactory();
        $zhangsan1 = $flyweight->getFlyweight('170cm的模特');
        $zhangsan1->show('第1件L号的衣服');

        $zhangsan2 = $flyweight->getFlyweight('170cm的模特');
        $zhangsan2->show('第99件L号的衣服');

        var_dump($zhangsan1 === $zhangsan2);
        echo '<hr>';

        $lisi = $flyweight->getFlyweight('180cm的模特');
        $lisi->show('第1件XXL号的衣服');

        $wangmazi = new UnsharedConcreteFlyweight('190cm的模特');
        $wangmazi->show('第1件XXXL号的衣服');
        $wangmazi->delete();
        $wangmazi->show('第1件XXXL号的衣服');
    }
}

$client = new Client();
$client->run();

从示例中我们可以看出;
170的模特一直是一个人;
节省大量的内存;
这样的特性使得享元模式可以运用于数据库连接池以及缓冲池等场景;
但是享元模式也有缺点;
一个是增加了代码的复杂度;
上面代码中就把模特分成了可以共享的通用享元类;
和有无法共享的代码的非共享享元类;
再个是需要有一个享元工厂;
这个工厂往复杂了写就是一个连接池了;
当类比较少的时候反而为增加内存的占用了;

github示例:https://github.com/baijunyao/design-patterns/tree/master/Flyweight

白俊遥博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论