PHP设计模式(十三)享元模式的实现
一、什么是享元模式
**享元模式(Flyweight Pattern)**主要用于减少创建对象的数量,以减少内存占用和提高性能。
理解:
比如开发博客,小明需要新闻博客,小花需要图片博客......
这些博客都有一个释共同的特点:结构非常相似,如更换主题一样,
最先想到的可能是复制然后更改不同的文字,这是很繁琐的,
享元模式把可以共享的直接公共出来,不需要全部赋值,
直接更改不同的博客即可。
二、享元模式结构
抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共介面。那些需要外蕴状态的操作可以通过呼叫商业以引数形式传入
具体享元(ConcreteFlyweight)角色:实现Flyweight介面,并为内部状态(如果有的话)拉回储存空间。ConcreteFlyweight物件必须是可共享的。它所储存的状态必须是内部的
不共享的具体享元(UnsharedConcreteFlyweight)角色:并非所有的Flyweight子类都需要被共享。Flyweigth使共享成为可能,但它并不强制共享。
享元工厂(FlyweightFactory)角色:负责建立和管理享元角色。本角色必须保证享元物件可能被系统适当地共享
三、享元模式使用场景
1、一个应用程式使用了大量的物件
2、完全由于使用大量的物件,造成很大的储存开销
3、物件的大多数状态都可变为外部状态
4、如果删除物件的外部状态,那么可以用相对较少的共享物件取代很多组物件
5、应用程式不依赖于物件标识。
四、享元模式优缺点
优点:可以大幅度地降低记忆体中物件的数量
缺点:
1、使得系统更加复杂
2、享元模式将享元物件的状态外部化,而读取外部状态使得执行时间稍微变长
五、代码实现
Blog.php 相当于Flyweight抽象角色
<?php
/**
* 抽象Blog角色,相当于 Flyweight
*/
abstract class Blog
{
// 私用博客名,禁止子类直接使用
private $blogName;
public function __construct(string $blogName)
{
$this->setWebsiteName($blogName);
}
public function setWebsiteName(string $blogName)
{
$this->blogName = $blogName;
}
public function getWebsiteName()
{
return $this->blogName;
}
}
ConcreteBlog.php 相当于ConcreteFlyweight具体享元角色
<?php
/**
* ConcreteBlog具体享元角色实现,相当于ConcreteFlyweight
*/
class ConcreteBlog extends Blog
{
// 调用父类构造函数,初始化博客名
public function __construct(string $blogName){
parent::__construct($blogName);
}
public function show(User $user){
echo '这是 ' . $user->getUserName() . ' 的网站 ' . $this->getWebsiteName() . '<hr>';
}
}
BlogFactory.php 相当于FlyweightFactory享元工厂角色
<?php
/**
* BlogFactory享元工厂角色,FlyweightFactory
*/
class BlogFactory
{
// 存储工厂实例对象
private $blogs = [];
/**
* getBlog 生产对象
*
* @param int $key 实例标识号
* @param string $name 博客名
* @return object
*/
public function getBlog(int $key , string $name)
{
// 判断实例是否生产
if(!isset($this->blogs[$key])){
$this->blogs[$key] = new ConcreteBlog($name);
}
// 实例存在,返回实例对象
return $this->blogs[$key];
}
}
UnsharedBlog.php 相当于UnsharedConcreteFlyweight
<?php
class UnsharedBlog extends Blog
{
// 调用父类构造函数,初始化博客名
public function __construct(string $blogName){
parent::__construct($blogName);
}
public function show(){
echo '不共享的博客';
}
}
User.php
<?php
// 用户名
class User{
private $name;
public function __construct($name){
$this->setUserName($name);
}
public function setUserName($name){
$this->name = $name;
}
public function getUserName(){
return $this->name;
}
}
index.php 客户端实现 <?php
include './Blog.php';
include './ConcreteBlog.php';
include './UnsharedBlog.php';
include './BlogFactory.php';
include './User.php';
class index
{
public static function idx()
{
$flyweight = new BlogFactory();
$website = $flyweight->getBlog(1,'blog');
$website->show(new User('李四'));
$wangwu = $flyweight->getBlog(1 , 'Liblog');
$wangwu->show(new User('王五'));
$zhaoliu = $flyweight->getBlog(2 , '论坛');
$zhaoliu->show(new User('赵六'));
// 简单实现不共享
$unblog = new UnsharedBlog('不共享');
$unblog->show();
}
}
Index::idx();
我是夕阳何处寻,期待和优秀的你一起同行!
夕阳何处寻
2020年04月19日