什么是享元模式
享元,共享的元素,什么叫共享,就是把东西分享出来,放到一个地方,可以让其他人享用。然而在程序中,这个元素我们可以暂时理解为各种对象、各种类,把他们放到一个数组里,方便统一管理和调用。说起来有点像注册模式和组合模式,都是把类给放到数组里,但是区别是注册模式中的数组元素间没有必然联系,不相互依赖;组合模式是树形结构,具有层级依赖,同级之间不依赖,并且这些元素大致相同,因为它们继承于同一个接口;享元模式类似于组合模式,只不过它采用了一个单独的工厂类来存储类的实例,它的每个元素都必须是至少两个类的组合构成。
使用场景
比如发送短信,有x个第三方短信平台阿里云、腾讯,有m个短信模板,有n个收信人,一共三个对象。如果用传统的开发模式,则每次发送短信的时候都要实例化一个平台类、一个模板类和一个收信人类,那么需要xmn个同样的操作才能给所有人发送短信,显然性能很低。此时就适合享元模式,把怕平台和模板的组合存到数组里,随用随取,减少类的创建,降低资源消耗。
示意图
优点
减少类的创建,节省系统资源,提升性能,并且易扩展,符合设计原则的单一原则和开闭原则。
代码实例
目录结构
Message.php 短信平台接口类
interface Message{
/**
* 发送短信
* @param User $user
* @return mixed
*/
function send(User $user);
}
Ali.php 阿里短信平台类
class Ali implements Message{
public $template; //短信模板类
public function __construct(Template $template)
{
//设置短信模板
$this->template = $template;
}
public function send(User $user)
{
// TODO: Implement send() method.
echo "<pre>";
echo '用阿里云短信向'.$user->name.'发送:'.$this->template->getTemplate().PHP_EOL;
}
}
Tx.php 腾讯短信平台类
class Tx implements Message{
public $template;//短信模板类
public function __construct(Template $template)
{
//设置短信模板
$this->template = $template;
}
public function send(User $user)
{
// TODO: Implement send() method.
echo '用阿里云短信向'.$user->name.'发送:'.$this->template->getTemplate(),PHP_EOL;
}
}
Template.php 短信模板类
class Template{
public $template; //短信模板
public function __construct($template)
{
//设置短信模板
$this->template = $template;
}
/**
* 获取短信模板
* @return mixed
*/
function getTemplate(){
return $this->template;
}
}
Factory.php 享元工厂类
<?php
class Factory{
public $message=[];
/**
* 根据key获取要使用的发短信类实例
* @param $key
* @param $template
* @return mixed
*/
function getMessage($key,$template){
if (!isset($this->message[$key])){
$this->message[$key] = $template;
}
return $this->message[$key];
}
//调用平台的send方法发送短信
function send($user){
foreach ($this->message as $message){
$message->send($user);
}
}
}
User.php 收信人类
<?php
class User{
public $name;//用户名
public function __construct($name)
{
//设置用户名
$this->name = $name;
}
/**
* 获取用户名
* @return mixed
*/
function getName(){
return $this->name;
}
}
client.php 调用
<?php
require_once 'Message.php';
require_once 'Ali.php';
require_once 'Template.php';
require_once 'Tx.php';
require_once 'User.php';
require_once 'Factory.php';
//初始化三个短信模板
$template1 = new Template('模板1');
$template2 = new Template('模板2');
$template3 = new Template('模板3');
//阿里云平台类与模板类绑定
$ali1 = new Ali($template1);
$ali2 = clone $ali1;
$ali3 = clone $ali1;
$ali2->template = $template2;
$ali3->template = $template3;
//腾讯平台类与模板类绑定
$tx1 = new Tx($template1);
$tx2 = clone $tx1;
$tx3 = clone $tx1;
$tx2->template = $template2;
$tx3->template = $template3;
//享元工厂存储这些绑定关系
$factory = new Factory();
$factory->getMessage(md5($template1->template.'ali'),$ali1);//存储阿里云平台与模板1的绑定
$factory->getMessage(md5($template2->template.'ali'),$ali2);//存储阿里云平台与模板2的绑定
$factory->getMessage(md5($template3->template.'ali'),$ali3);//存储阿里云平台与模板3的绑定
$factory->getMessage(md5($template1->template.'tx'),$tx1);//存储阿里云平台与模板1的绑定
$factory->getMessage(md5($template3->template.'tx'),$tx3);//存储阿里云平台与模板3的绑定
//收信人
$user1 = new User('王五');
$user2 = new User('李四');
//分别发送
$factory->send($user1);
$factory->send($user2);
运行结果