使用共享物件,尽可能减少内存使用量以分享更多的内容给相似的组件。
使用情景
享元模式适用于大量组件重复而导致占用了大量内存。这时组件中的大部分内容都是重复的,这些重复的内容可以共享给其他的相似组件。常见的做法是把他们放在外部数据结构,需要时传递给享元
例如在文本编辑器中以图形结构来表示字符,但是每个字符有其外观字重等等信息,这使得每个字符都会占用大量空间。取而代之的是,使用享元模式,每个字符传递到一个共享的字符组件,这个组件被所有其他字符所共享,这样只有每个字符本色内容才会被额外的储存。
代码实现
享元接口,指定了 render 方法用于渲染字符
interface FlyweightInterface
{
public function render(string $extrinsicState);
}
具体的享元类,实现了具体如何去使用给定的字符内容与字体来渲染字符
class CharacterFlyweight implements FlyweightInterface
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function render($font)
{
return sprintf('Character %s with font %s', $this->name, $font);
}
}
使用工厂来生产享元类
class FlyweightFactory implements \Countable
{
private $pool = [];
public function get($name)
{
if (!isset($this->pool[$name])) {
$this->pool[$name] = new CharacterFlyweight($name);
return $this->pool[$name];
}
}
public function count()
{
return count($this->pool);
}
}
测试
如测试代码中,将所有的字符与可能的自体单独储存在另外的数据结构中,在需要是使用工厂来生产享元类以渲染指定的字符
class Test
{
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 run()
{
$factory = new FlyweightFactory();
$flyweight = $factory->get($this->characters[0]);
$rendered = $flyweight->render($this->fonts[1]);
var_dump($rendered);
}
}
输出
string(38) "Character a with font Times New Roman"