享元模式主要是把常用的对象放到内存中,用的时候直接从内存中读取,而不是再次重新新建,减少内存占用量,提高效率。
享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。这就是享元模式。
享元模式涉及到三个角色:
享元工厂角色:创建并管理对象,主要是这个工厂来控制。
所有具体享元父接口角色:接受并作用与外部状态。
具体享元角色:具体变化点,为内部对象增加储存空间。
意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
何时使用:1、系统中有大量对象。2、这些对象消耗大量内存。3、这些对象的状态大部分可以外部化。4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。5、系统不依赖于这些对象身份,这些对象是不可分辨的。
如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
关键代码:用 HashMap 存储这些对象,PHP的数组实质也是HashMap。
应用实例:1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。2、数据库的数据池。
优点:大大减少对象的创建,降低系统的内存,使效率提高。
缺点:提高了系统的负责度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
使用场景:1、系统有大量相似对象。2、需要缓冲池的场景。
注意事项:1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。2、这些类必须有一个工厂对象加以控制。
下边是代码:
<?php
//抽象类
abstract class Flyweight{
public $Name;
abstract function ShowName();
}
//具体实现
class ConcreteFlyweight extends Flyweight{
function __construct($Name)
{
$this->Name = $Name;
}
function ShowName()
{
echo " Name is ".$this->Name;
}
}
//一个工厂,如果有则返回,没有则新建
class FlyweightFactory{
private $Flyweights = array();
function GetFlyweight($Name)
{
if(isset($this->Flyweights[$Name]))
{
return $this->Flyweights[$Name];
}
else
{
$Flyweight = new ConcreteFlyweight($Name);
$this->Flyweights[$Name] = $Flyweight;
return $Flyweight;
}
}
function GetSize()
{
echo " The size of the Array is ".count($this->Flyweights);
}
}
//调用,创建工厂,根据不同name得到不同对象
$Factory = new FlyweightFactory();
$Fly1 = $Factory->GetFlyweight("Google");
$Fly2 = $Factory->GetFlyweight("Baidu");
$Fly3 = $Factory->GetFlyweight("Google");
$Fly4 = $Factory->GetFlyweight("Google");
$Fly5 = $Factory->GetFlyweight("Google");
//执行显示方法
$Fly1->ShowName();
$Fly2->ShowName();
$Fly3->ShowName();
$Fly4->ShowName();
$Fly5->ShowName();
//显示对象个数,输出2
$Factory->GetSize();
?>