定義
運用共享技術有效地支援大量細粒度物件的複用。
系統只使用少量的物件,而這些物件都很相似,狀態變化很小,可以實現物件的多次複用。
享元概念
內部狀態
在享元物件中可共享的狀態叫內部狀態。
外部狀態
在享元物件中不可共享的狀態叫外部狀態。
享元池
享元工廠裡面存在享元物件的變數叫做享元池。
設計的原則和思想
- 解耦的是享元物件中的內部狀態和外部狀態。
- 不變部分是內部狀態,變化部分是外部狀態。
- 核心思想是物件複用,節省記憶體。
一句話概括設計模式
共享物件。
結構中包含的角色
- Flyweight(抽象享元類)
- ConcreteFlyweight(具體享元類)
- UnsharedConcreteFlyweight(非共享具體享元類)
- 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);
優點
- 大大減少物件的建立,使效率提高。
- 節省記憶體,減少記憶體中物件的數量。
- 享元物件可以在不同的環境中被共享。
缺點
- 分離出內部狀態和外部狀態,使系統和程式碼都更加複雜。
何時使用
- 有大量相同或者相似的物件,造成記憶體的大量耗費。
- 需要多次重複使用享元物件時。
- 程式必須支援大量物件且沒有足夠的記憶體容量時。
- 需要緩衝池的場景。
實際應用場景
- JAVA 中的 String。
- 資料庫的連線池。
享元模式 VS 物件池模式 VS 多例模式
享元模式
- 主要目的是節省空間。
- 在整個生命週期中,是被所有使用者共享的。
- 主要用於減少建立物件的數量,以減少記憶體佔用和提高效能。
- 一個類可以建立多個物件,每個物件被多處程式碼引用共享。
物件池模式
- 主要目的是節省時間。
- 在任意時刻都不會被多處使用,而是被一個使用者獨佔,當使用完成之後,放回到池中,再由其他使用者重複利用。
多例模式
- 主要目的是為了限制物件的個數。
本作品採用《CC 協議》,轉載必須註明作者和本文連結