极简设计模式-享元模式

享元模式 - Flyweight Pattern

定义

运用共享技术有效地支持大量细粒度对象的复用。
系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。

享元概念

内部状态
    在享元对象中可共享的状态叫内部状态。
外部状态
    在享元对象中不可共享的状态叫外部状态。
享元池
    享元工厂里面存在享元对象的变量叫做享元池。

设计的原则和思想

  1. 解耦的是享元对象中的内部状态和外部状态。
  2. 不变部分是内部状态,变化部分是外部状态。
  3. 核心思想是对象复用,节省内存。

一句话概括设计模式

共享对象。

结构中包含的角色

  1. Flyweight(抽象享元类)
  2. ConcreteFlyweight(具体享元类)
  3. UnsharedConcreteFlyweight(非共享具体享元类)
  4. FlyweightFactory(享元工厂类)

最小可表达代码

// 抽象享元类  
abstract class Flyweight {} 

// 具体享元类  
class ConcreteFlyweight extends Flyweight {}

// 非共享具体享元类
class UnsharedConcreteFlyweight extends Flyweight 
{
    private $flyweights = [];

    public function add($id, $flyweight)
    {
        $this->flyweights[$id] = $flyweight;
    }
}

// 享元工厂类
class FlyweightFactory 
{
    private static $flyweights = [];

    public static function getFlyweightById(int $id)
    {  
        if (empty(static::$flyweights[$id])) {
            var_dump("生成ID : {$id}");
            static::$flyweights[$id] = new ConcreteFlyweight();
        }

        return static::$flyweights[$id];
    }

    public static function getUnsharedConcreteFlyweightByIds(array $ids)
    {  
        $unsharedConcreteFlyweight = new UnsharedConcreteFlyweight(); 

        foreach ($ids as $id) {
            $unsharedConcreteFlyweight->add($id, self::getFlyweightById($id));
        }

        return $unsharedConcreteFlyweight;
    }  
}

$id = 1;
$ids = [1,2];
$flyweight = FlyweightFactory::getFlyweightById($id);
$unsharedConcreteFlyweight = FlyweightFactory::getUnsharedConcreteFlyweightByIds($ids);

优点

  1. 大大减少对象的创建,使效率提高。
  2. 节省内存,减少内存中对象的数量。
  3. 享元对象可以在不同的环境中被共享。

缺点

  1. 分离出内部状态和外部状态,使系统和代码都更加复杂。

何时使用

  1. 有大量相同或者相似的对象,造成内存的大量耗费。
  2. 需要多次重复使用享元对象时。
  3. 程序必须支持大量对象且没有足够的内存容量时。
  4. 需要缓冲池的场景。

实际应用场景

  1. JAVA 中的 String。
  2. 数据库的连接池。

享元模式 VS 对象池模式 VS 多例模式

享元模式

  1. 主要目的是节省空间。
  2. 在整个生命周期中,是被所有使用者共享的。
  3. 主要用于减少创建对象的数量,以减少内存占用和提高性能。
  4. 一个类可以创建多个对象,每个对象被多处代码引用共享。

对象池模式

  1. 主要目的是节省时间。
  2. 在任意时刻都不会被多处使用,而是被一个使用者独占,当使用完成之后,放回到池中,再由其他使用者重复利用。

多例模式

  1. 主要目的是为了限制对象的个数。
本作品采用《CC 协议》,转载必须注明作者和本文链接
Long2Ge
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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