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 相关文章推荐
php处理json时中文问题的解决方法
Apr 12 PHP
MySQL时间字段究竟使用INT还是DateTime的说明
Feb 27 PHP
php提示无法加载或mcrypt没有找到 PHP 扩展 mbstring解决办法
Mar 27 PHP
工厂模式在Zend Framework中应用介绍
Jul 10 PHP
destoon实现商铺管理主页设置增加新菜单的方法
Jun 26 PHP
PHP打开和关闭文件操作函数总结
Nov 18 PHP
WordPress中限制非管理员用户在文章后只能评论一次
Dec 31 PHP
PHP获取当前URL路径的处理方法(适用于多条件筛选列表)
Feb 10 PHP
Laravel使用PHPQRCODE实现生成带有LOGO的二维码图片功能示例
Jul 07 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
Jul 20 PHP
PHP PDOStatement::bindColumn讲解
Jan 30 PHP
php 利用socket发送GET,POST请求的实例代码
Jul 04 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 header函数分析详解
2011/08/06 PHP
深入解析PHP内存管理之谁动了我的内存
2013/06/20 PHP
Thinkphp单字母函数使用指南
2016/05/08 PHP
php微信开发之关注事件
2018/06/14 PHP
jQuery EasyUI API 中文文档 - DataGrid数据表格
2011/11/17 Javascript
js二维数组排序的简单示例代码
2014/01/24 Javascript
JQuery给元素绑定click事件多次执行的解决方法
2014/05/29 Javascript
js实现简单随机抽奖的方法
2015/01/27 Javascript
JavaScript定时器制作弹窗小广告
2017/02/05 Javascript
JS中利用localStorage防止页面动态添加数据刷新后数据丢失
2017/03/10 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
2017/04/13 jQuery
vue2.X组件学习心得(新手必看篇)
2017/07/05 Javascript
vue.js2.0点击获取自己的属性和jquery方法
2018/02/23 jQuery
JS中的回调函数实例浅析
2018/03/21 Javascript
jQuery实现获取选中复选框的值实例详解
2018/06/28 jQuery
JSON是什么?有哪些优点?JSON和XML的区别?
2019/04/29 Javascript
vue登录注册实例详解
2019/09/14 Javascript
vue 解决computed修改data数据的问题
2019/11/06 Javascript
vue data对象重新赋值无效(未更改)的解决方式
2020/07/24 Javascript
JavaScript中作用域链的概念及用途讲解
2020/08/06 Javascript
[46:20]TFT vs Secret Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
Python编程pygame模块实现移动的小车示例代码
2018/01/03 Python
在Django中输出matplotlib生成的图片方法
2018/05/24 Python
基于Django静态资源部署404的解决方法
2019/07/28 Python
win10从零安装配置pytorch全过程图文详解
2020/05/08 Python
浅析关于Keras的安装(pycharm)和初步理解
2020/10/23 Python
美国家具网站:Cymax
2016/09/17 全球购物
法院实习人员自我鉴定
2013/09/26 职场文书
养殖项目策划书范文
2014/01/13 职场文书
爷爷追悼会答谢词
2014/01/24 职场文书
室内设计专业自荐信
2014/05/31 职场文书
2014年房产销售工作总结
2014/12/08 职场文书
公务员年度考核个人总结
2015/02/12 职场文书
大学生自我评价范文
2015/03/03 职场文书
2015年客服工作总结范文
2015/04/02 职场文书
2015年煤矿工作总结
2015/04/28 职场文书