php设计模式 FlyWeight (享元模式)


Posted in PHP onJune 26, 2011

享元模式英文称为“Flyweight Pattern”,我非常感谢将Flyweight Pattern翻译成享元模式的那位强人,因为这个词将这个模式使用的方式明白得表示了出来;如果翻译成为羽量级模式或者蝇量级模式等等,虽然可以含蓄的表现出使用此模式达到的目的,但是还是没有抓住此模式的关键。

享元模式的定义为:采用一个共享来避免大量拥有相同内容对象的开销。这种开销中最常见、直观的就是内存的损耗。享元模式以共享的方式高效的支持大量的细粒度对象。

在名字和定义中都体现出了共享这一个核心概念,那么怎么来实现共享呢?要知道每个事物都是不同的,但是又有一定的共性,如果只有完全相同的事物才能共享,那么享元模式可以说就是不可行的;因此我们应该尽量将事物的共性共享,而又保留它的个性。为了做到这点,享元模式中区分了内蕴状态和外蕴状态。内蕴状态就是共性,外蕴状态就是个性了。

注:共享的对象必须是不可变的,不然一变则全变(如果有这种需求除外)。

内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的;外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。在每个具体的环境下,客户端将外蕴状态传递给享元,从而创建不同的对象出来。

先看看下面程序,大概了解下享元模式。

<?php 
/** 
* 享元模式 
* 
* 运用享元技术有效的支持大量细粒度的对象 
*/ 
class CD 
{ 
private $_title = null; 
private $_artist = null; 
public function setTitle($title) 
{ 
$this->_title = $title; 
} 
public function getTitle() 
{ 
return $this->_title; 
} 
public function setArtist($artist) 
{ 
$this->_artist = $artist; 
} 
public function getArtist($artist) 
{ 
return $this->_artist; 
} 
} 
class Artist 
{ 
private $_name; 
public function __construct($name) 
{ 
echo "construct ".$name."<br/>"; 
$this->_name = $name; 
} 
public function getName() 
{ 
return $this->_name; 
} 
} 
class ArtistFactory 
{ 
private $_artists = array(); 
public function getArtist($name) 
{ 
if(isset($this->_artists[$name])) 
{ 
return $this->_artists[$name]; 
} else { 
$objArtist = new Artist($name); 
$this->_artists[$name] = $objArtist; 
return $objArtist; 
} 
} 
} 
$objArtistFactory = new ArtistFactory(); 
$objCD1 = new CD(); 
$objCD1->setTitle("title1"); 
$objCD1->setArtist($objArtistFactory->getArtist('artist1')); 
$objCD2 = new CD(); 
$objCD2->setTitle("title2"); 
$objCD2->setArtist($objArtistFactory->getArtist('artist2')); 
$objCD3 = new CD(); 
$objCD3->setTitle("title3"); 
$objCD3->setArtist($objArtistFactory->getArtist('artist1'));

享元模式的精要有三点:

  1. 被系统大量使用的细粒度对象,粒度要有多细,量要有多大,看看jdk中使用的享元模式就知道了,jdk中,Integer,Character,String等都使用了享元模式,他们都是最基础的数据类型,不可谓不细,他们频繁的参与运算,不可谓不大量。
  2. 划分对象的内蕴属性/状态和外蕴属性/状态;所谓内蕴状态,就是存在对象的内部,不会随着环境变化的状态, 有一个网友说的很好,就是无区别的状态, 即拿掉外蕴属性之后同一类对象没有区别对象的内蕴状态就是对象的元神,只要元神元神无区别,那么对象也就无区别,同时也只有这些无区别的元神可以被共享,我想这也是Flyweight被翻译成享元的原因。外蕴状态就是由客户端指定,会随着环境变化的状态; 对于Integer来说, 他的内蕴属性其实就是他的value(当然它也没有外蕴属性);
  3. 用一个工厂控制享元的创造;因为享元对象不能被客户端随意创造, 否则就没有意义了。工厂通常提供缓存机制保存已经创造的享元。

面向对象虽然很好地解决了抽象性的问题,但是对于一个实际运行的软件系统,我们还需要考虑面向对象的代价问题,享元模式解决的就是面向对象的代价问题。享元模式采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。

享元模式在一般的项目开发中并不常用,而是常常应用于系统底层的开发,以便解决系统的性能问题。Java和.Net中的String类型就是使用了享元模式。如果在Java或者.NET中已经创建了一个字符串对象s1,那么下次再创建相同的字符串s2的时候,系统只是把s2的引用指向s1所引用的具体对象,这就实现了相同字符串在内存中的共享。如果每次执行s1=“abc”操作的时候,都创建一个新的字符串对象的话,那么内存的开销会很大。

PHP 相关文章推荐
动易数据转成dedecms的php程序
Apr 07 PHP
PHP实时显示输出
Oct 02 PHP
在PHP中操作Excel实例代码
Apr 29 PHP
初品cakephp 入门基础
Feb 16 PHP
解析file_get_contents模仿浏览器头(user_agent)获取数据
Jun 27 PHP
PHP面向对象程序设计之类常量用法实例
Aug 20 PHP
php将字符串随机分割成不同长度数组的方法
Jun 01 PHP
PHP添加图片水印、压缩、剪切的封装类
Aug 17 PHP
PHP响应post请求上传文件的方法
Dec 17 PHP
Ubuntu VPS中wordpress网站打开时提示”建立数据库连接错误”的解决办法
Nov 03 PHP
PHP实现的激活用户注册验证邮箱功能示例
Jun 06 PHP
Ajax+PHP实现的分类列表框功能示例
Feb 11 PHP
php设计模式 Mediator (中介者模式)
Jun 26 #PHP
php设计模式 Prototype (原型模式)代码
Jun 26 #PHP
PHP如何解决网站大流量与高并发的问题
Jun 25 #PHP
session在PHP大型web应用中的使用
Jun 25 #PHP
php URL跳转代码 减少外链
Jun 25 #PHP
php session安全问题分析
Jun 24 #PHP
使用PHP实现二分查找算法代码分享
Jun 24 #PHP
You might like
php图片处理函数获取类型及扩展名实例
2014/11/19 PHP
php设置静态内容缓存时间的方法
2014/12/01 PHP
php面向对象中static静态属性和静态方法的调用
2015/02/08 PHP
PHP实现财务审核通过后返现金额到客户的功能
2019/07/04 PHP
TFDN图片播放器 不错自动播放
2006/10/03 Javascript
在IE上直接编辑网页内容的js代码(IE地址栏js)
2009/04/27 Javascript
$.ajax返回的JSON无法执行success的解决方法
2011/09/09 Javascript
jstree单选功能的实现方法
2017/06/07 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
2017/08/19 Javascript
jquery插件开发之选项卡制作详解
2017/08/30 jQuery
Vue中render函数的使用方法
2018/01/31 Javascript
微信小程序实现底部导航
2018/11/05 Javascript
详解使用React.memo()来优化函数组件的性能
2019/03/19 Javascript
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
2019/04/26 Javascript
基于JS抓取某高校附近共享单车位置 使用web方式展示位置变化代码实例
2019/08/27 Javascript
layui表单提交到后台自动封装到实体类的方法
2019/09/12 Javascript
原生微信小程序开发中 redux 的使用详解
2021/02/18 Javascript
[45:34]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第一场 12.18
2020/12/19 DOTA
按日期打印Python的Tornado框架中的日志的方法
2015/05/02 Python
Python安装使用命令行交互模块pexpect的基础教程
2016/05/12 Python
Django之提交表单与前后端交互的方法
2019/07/19 Python
tensorflow多维张量计算实例
2020/02/11 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
2020/02/17 Python
基于Python正确读取资源文件
2020/09/14 Python
Django contrib auth authenticate函数源码解析
2020/11/12 Python
python中子类与父类的关系基础知识点
2021/02/02 Python
澳大利亚第一旅行车和房车配件店:Caravan RV Camping
2020/12/26 全球购物
北承题目(C++)
2012/05/16 面试题
如何在发生故障的节点上重新安装 SQL Server
2013/03/14 面试题
制衣厂各岗位职责
2013/12/02 职场文书
弘扬雷锋精神活动演讲稿
2014/03/04 职场文书
北京申奥口号
2014/06/19 职场文书
2015大学生实训报告
2014/11/05 职场文书
医院营销工作计划
2015/01/16 职场文书
食品卫生管理制度
2015/08/06 职场文书
详解使用内网穿透工具Ngrok代理本地服务
2022/03/31 Servers