享元模式
<h3>享元模式目的</h3>
<ul>
<li>池技术的重要实现方式,运用共享技术有效的支持大量的细粒度对象,用于减少创建对象的数量,以减少内存占用和提高性能。</li>
<li>为了节约内存的使用,享元模式会尽量使类似的对象共享内存。在大量类似对象被使用的情况中这是十分必要的。</li>
<li>常用做法是在外部数据结构中保存类似对象的状态,并在需要时将他们传递给享元对象。</li>
</ul>
<h3>为什么需要享元模式</h3>
<ul>
<li>在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。</li>
<li>系统有大量相似对象。</li>
<li>需要缓冲池的场景。</li>
</ul>
<h3>理解</h3>
<ul>
<li>享元模式在PHP中可能比较少遇,</li>
<li>但在Java中常常有这种情况。就是代码产生了大量的对象,虽然使用完有释放,但是由于垃圾回收需要一定时间,导致内存被耗尽。</li>
<li>PHP经常应用web编程,脚本执行时间很短(30秒)。所以很少遇见这种情况,甚至我们使用完变量,连unset()函数都不用调用,就等着脚步执行结束后,自动释放。
但是如果你试过在cli模式下运行PHP脚本,做一些socket通信,发送邮件等长耗时或是多连接任务时,就难免会遇到这种情况。</li>
</ul>
<h3>优点</h3>
<ul>
<li>可以大幅度地降低内存中对象的数量</li>
</ul>
<h3>缺点</h3>
<ul>
<li>使得系统更加复杂</li>
<li>将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长</li>
</ul>
<h3>适用场景:</h3>
<ul>
<li><strong>当一下情况成立时使用Flyweight模式</strong></li>
<li>一个应用程序使用了大量的对象</li>
<li>完全由于使用大量的对象,造成很大的存储开销</li>
<li>对象的大多数状态都可变为外部状态</li>
<li>如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象</li>
<li>应用程序不依赖于对象标识</li>
</ul>
<h2>代码示例</h2>
<pre><code class="language-PHP"><?php
//抽象享元对象
abstract class Flyweight{
//考点
public $address;
//享元角色必修设置考点
public function __construct($address){
$this->address = $address;
}
}
//具体享元角色 考生类
class ConcreteFlyweight extends Flyweight{
//报考动作
public function register(){
echo "我的报考点是:{$this->address}".PHP_EOL;
}
//退出
public function quit(){
unset($this);
}
}
//享元工厂 缓冲池
class FlyweightFactor{
static private $students = array();
static public function getStudent($address){
$students =self::$students;
//判断该键值是否存在
if(array_key_exists($address,$students)){
echo "缓冲池有考点为{$address},从池中直接取".PHP_EOL;
}else{
echo "缓冲池没有,创建了考点为{$address}的对象并放到池中".PHP_EOL;
self::$students[$address] = new ConcreteFlyweight($address);
}
return self::$students[$address];
}
}
//实例化学生对象
$student_1 = FlyweightFactor::getStudent('广州');
//报考
$student_1 ->register();
// 退出
$student_1->quit();
//第二个学生进来
$student_2 = FlyweightFactor::getStudent('东莞');
//报考
$student_2 ->register();
// 退出
$student_2->quit();
//第三个学生进来
$student_3 = FlyweightFactor::getStudent('广州');
//报考
$student_3 ->register();
// 退出
$student_3->quit();
</code></pre>