老王的看法,不过,事实上就是这样,现在很多开发人员还是很少在运行时候把对象作为参数传给某个方法或者class
原文:http://hi.baidu.com/thinkinginlamp/blog/item/ea586b63472627680c33fa38.html
正文:
写在前面的话:PHP每次运行重建环境,这样的运行方式本身就决定了PHP没有传统意义上的单例。
单例模式(singleton)也被叫做单件模式。使用它的目的是为了确保某个类只有一个实例。因为它的实现方式很简单,所以多数模式书籍都把单例模式作 为入门模式来介绍,可以说对很多模式爱好者来说,单例模式是他们最熟悉的设计模式。可惜这间接造成了单例模式使用的泛滥,以至于到了无所不在的地步,比如 说,ZendFramework里连前端控制器都是单例的。那么,单例模式是邪恶的么?
下面看一个实际编程时很多人愿意采用的单例模式例子:
注意:正常的单例模式应该设置一个私有化的__construct,但是出于下文的需要,我省略的它,至于限制__clone的行为,因为我嫌它占地方, 所以也没写,这两点你自己注意一下就好了,和文本讨论的问题关系不大。完整的例子可以参考:http://www.php.net/manual/en /language.oop5.patterns.php。
class Database
{
private static $instance;
public static function getInstance()
{
if (!isset(self::$instance)) {
$class = __CLASS__;
self::$instance = new $class;
}
return self::$instance;
}
}
如此的单例模式通常是这样调用的:
class Article
{
private $dasebase;
public function __construct()
{
$this->database = Database::getInstance();
}
}
$article = new Article();
下面我们就来讨论一下这样使用单例模式好还是不好。
文章在构造函数内通过单例模式的方式得到数据库实例,这看起来很正常,但是对于文章这样的领域概念来说,数据库实例属于纯粹的技术实现手段,明显属于外来 物,应该尽可能隔离才对,这样才符合单一原则,在测试驱动开发的领域,这被称作MOCK,但是在上例中,由于我们是在构造函数里通过单例模式静态方法调用 得到的数据库对象,这就造成了没有办法从外部替换掉这个数据库对象。
为了克服这样的问题,按照如下的方式获取数据实例更好一些:
class Article
{
private $dasebase;
public function __construct($database)
{
$this->database = $database;
}
}
$database = Database::getInstance();
$article = new Article($database);
一旦我们把数据库实例化的过程放到了外面,便可以随意替换掉其具体的实现方式,这很棒,特别是在测试的时候很有用,因为数据库环境是一个很大的不安定因 素,替换掉它有助于让测试用例更高效的运行。你甚至可以把程序搞得再智能化一点,一切外部对象依赖都通过容器注入的方式挂接。
此时再看看上面代码里的$database = Database::getInstance($database);突然又感觉有点莫名其妙,因为实在看不到在这里使用单例模式有什么额外的好处,直接按照最平常的实例化方式并没有什么不妥:
$database = new Database();
$article = new Article($database);
外部数据库对象通过构造函数的方式注入到文章里,保存在$this->database属性中,至于文章级联的评论 ($article->comments)也需要数据库实例这样的情况,可以在实例化评论的时候把文章的$this->database属性 通过评论构造函数注入的方式传递过去,当然,还有其它的方法,总而言之,你不再需要一个单例模式的数据库实例。
再回到单例模式的本意上:为了确保某个类只有一个实例。比如说公司只有一个CEO(如果有一个公司有多个CEO,那么这个公司必然会犯很多逻辑错误)。但 是反思现在很多人对单例模式的使用,往往并没有按照单例模式的本意来使用,拿上面的数据库例子来说,如果文章有一个数据库实例,评论有另一个数据库实例。 这有什么逻辑问题么?答案是没有。既然不必确保数据库只有一个实例,那么在这里使用单例模式的动机本身就值得推敲。当然,有人会说文章和评论使用不同的数 据库实例本身就低效。但如果仅仅是出于效率的考虑来使用单例模式,那么本质上不符合单例模式的定义,更何况即便不使用单例模式,我们也可以像文中的例子一 样通过注入的方式来解决所谓的低效问题。
写在后面的话:单例模式本身并不邪恶,邪恶的是在错误的环境下使用单例模式。不要为了单例而单例。
又一篇不是我写的东西,不错,对于WEB开发人员来说还是有参考意义的。所以我就贴了回来,也可以做个参考吧。。
原文:摘自:http://xinsync.xju.edu.cn/index.php/archives/4504
2006年10月份,我开始对web开发产生了兴趣,并决定自己也尝试开发一个网站。在此之前,我做过3年的java application的开发,对web开发应该算一无所知。在比较了java,php,ror,和python后,我选择了基于python的web框 架 - django 。到目前为止,我还认为这是一个明智的决定。Django高效的开发效率让我仅仅用一个月的业余时间,就基本完成了网站的开发。这是一个网络书签的网站, 我加上了一些有意思的特性,让网站显得有些与众不同。
我购买了域名和Dreamhost 的主机空间。Dreamhost支持django,并且第一年的费用只有180元人民币。2006年11月份,http: //www.hpbookmarks.com 上线了。网友们发来了善意的评论,“很有创意”,“点意思”,“一些feature很不错”。同时,还有一个非常一致的意见就是,“访问速度太慢了”。其 实,当时的情况不只是访问速度慢,而且是相当不稳定。很多时候是几个小时网站无法访问。当时,我并没有在意,因为我有两个自以为“合理”的解释。第一,我 用的是国外最便宜的虚拟主机,国内访问慢是很正常的。第二,django的还处于0.95的状态,效率和稳定性方面有问题也正常。
但是,我慢慢发现上面的解释不过是自己骗自己的借口。很多用dreamhost的网站,访问起来也很快。而且django也已经被成功应用在许多 大型的网站。我开始认真考虑提高网站速度的问题了。毕竟,速度慢的网站很可能在第一次就失去的用户,他们可以永远不会再来了。终于,我进行了下面一步一步 的优化工作,并且取得了一个看起来还不错的结果。
第一步,用Ajax提高用户体验
由于我的网站上链接字体的大小是根据点击次数决定,所以每次点击都要提交到服务器端并记录次数,再在客户端打开网站链接。这在localhost 测试的时候没有发现问题,但是部署到服务器上,会感到明显的等待。解决办法就是用Ajax。用户点击网站链接后就直接打开,再通过Ajax将点击的事件提 交到服务器端记录。这样用户感觉不到任何延时。
第二步,将逻辑移到客户端的javascript中
在开始的时候,“网站标签高亮”和“手气不错”的功能都是提交到服务器端操作,然后返回结果的。后来,我发现其实很多逻辑是可以移到客户端,由 javascript来实现的。Javascript非常强大,可以完成很多复杂的逻辑。将逻辑移到客户端的javascript中,可以很有效的减少和 服务器通讯的次数,获得更好的访问速度。
第三步,解决进程的
由于采用的是fastCGI的方式,我配置了django.fcgi。可是,我发现系统进程中,有大量的django.fcgi进程被标记为 < defunct>(失去功能)。这些进程会导致服务器有时无法正常访问。我开始尝试用命令来kill掉这些进程,但是很快发现这无法从根本上解决问 题。后来,我看到一个老外在blog上提到一个解决方案,将django.fcgi改名为dispatch.fcgi。原来,dispatch.fcgi 是一个dreamhost的系统进程,它的健壮性是可以得到保障的。果然,我将django.fcgi改名为 dispatch.fcgi后,的现象再没有出现。
第四步,优化SQL语句
SQL语句的执行通常也是一个很花费时间的操作。经过检查,我发现我的一条SQL语句,是一个嵌套三层的子表查询。而这条SQL还必须是一个 Raw SQL,即不能采用django的OR Maping。这意味着不能被cache缓存,每次都是真刀真枪的执行。更失败的是,经过我的分析,这条SQL完全可以不执行。这是一次设计上的失误,标
准的over design(过渡设计)。当时,我是想通过数据库得到一个最精确的统计值。后来发现,这个值完全可以用一个近似的常量代替。优化SQL,尤其是避免不必要的SQL执行,带来的效果是非常明显的。
第五步,尽量减少页面大小
随着添加网站越来越多,有一天我发现django生成的首页已经达到了80k。我很清楚这是一个非常不能被接受的数字。我开始检查页面,很快发现 了线索。 第一,因为偷懒,页面中很多layout是用空格( )实现的。第二,因为为了增加代码可读行,调试方便,每行生成的页面都增加换行符 (\n)。第三,最糟糕的是,大量的用了
inline css。就是将css style直接嵌入标记块中。于是,我立即动手,用css的align解决layout,去掉\n,将inline css抽象到独立的css文件中。这样下来,在不更改任何内容的情况下,80k变成了57k。(补充:由于网站链接大部分是打开新窗口,所以用了大量的 target=_blank。在ylsdd的提示下,在html的head里增加了,又节约了4k。)
第六步,用gzip进行页面压缩
当我兴高采烈的把页面优化结果贴到了smth bbs上,却被直接泼了盆凉水。原来百分之二十几的优化结果,实在太一般了。ylsdd给我了一个很重要的线索,deflate。原来apache的 deflate模块可以把文件进行gzip压缩,压缩后的文件传到浏览器后再被解压。主流的浏览器都支持这种gzip的解压操作。于是,我在apache 的配置文
件中加入了Add OutputFilter DEFAULT html css js的语句。经过测试,css,js这些文本文件的压缩后都只有原来尺寸的25%。这里,和大家分享一个网站http: //www.port80software.com/products/httpzip/compresscheck 它的作用是检测你的网站是否被压缩,以及压缩比率等。
第七步,回归静态页面
新的问题又来了。原来deflate只支持静态文件的压缩。而我的首页是django动态生成的,deflate模块没有进行压缩。我突然想到, 网站的首页为什么不能是静态页面呢?于是,我增加了一个runtime的api,这个api提供的是和原来一样由django动态生成的页面。我又写了一 个 python的程序,通过urllib2模块下载这个动态生成的页面,并保存为index.html。我将网站的root映射到index.html这个 静态页面。最后,通过linux crontab定义一个行为,每五分钟执行一下这个python程序,生成新的index.html。值得一提的是,由于网络原因,python程序不一 定每次都能准确完整的下载动态生成的页面。所以我们必须再进行一个校验算法。当页面大小要超过一定数字,页面中出现某个校验字符串的情况下,才保存 index.html。这样,每次用户提交的访问,不是由服务器端动态生成页面,极大的节省了服务器端的开销。而静态页面又可以有效的被deflate压 缩。最后结果,首页被压缩为13k,为原来的22%。唯一的区别就是,新提交和推荐的网站不能立即出现在首页。但是我认为,这应该是可以被接受的。
至此,网站的优化工作基本完成。网站的访问速度从原来30秒以上,缩短到3秒左右,应该说算是一个飞跃。虽然,3秒的速度也不是非常快,但是,考虑到虚拟主机等客观原因,这个结果我还是满意的。原来感觉我的网站很慢的朋友们,也可以再试试。
以上的优化方案出自我的个人经验,并不一定适合所有网站。但是,它告诉我们一个事实。影响网站访问速度的不仅仅是服务器配置,网络带宽。也许,你 糟糕的设计,低效率的方案也是致命的因素。应当注意的是,优化工作也不能匆匆上手。一定要仔细研究,具体情况具体分析,得到统计数据,找到真正的问题所 在,再开始优化。相信自己,提高网站的访问速度并不是不可能。毕竟,Nothing is Impossible。祝大家成功。
本文来自冰山上的播客:http://xinsync.xju.edu.cn/index.php/archives/4476
还是值得记录一下,虽然效果一样,但正因为优先级的不同,导致结果可能会和预料中的值有偏差,虽然实际应用中不太用得到但,看看还是好的
原文:
PHP中&&和and都是逻辑运算符,且功能也是完全一样的。如果你不了解它俩的区别,你可能会留下很不容易发现的BUG。仔细看下面的代码片段(注释是执行结果):
<?php
$true = TRUE;
$false = FALSE;
$rt1 = $true && $false;//$rt1:FALSE
$rt2 = $true and $false;//$rt2:TRUE
var_dump($rt1);//FALSE
var_dump($rt2);//TRUE
var_dump($true && $false);//FALSE
var_dump($true and $false);//FALSE
这里最让人感到奇怪的就是为什么$rt1成了FALSE,而$rt2却是TRUE。其实这是PHP优先级在作怪。从文档中我们看到,赋值符号”=”的优先级低于逻辑与符号”&&”,但高于逻辑与符号”and”(也就是&& > = > and)。也就是说:
$rt1 = $true && $false;
$rt2 = $true and $false;
在PHP看来其实是:
$rt1 = ($true && $false);
($rt2 = $true) and $false;
这样就容易解释为什么会有那样的结果了。那现在你知道下面两句的结果了吗?
var_dump($rt1 = $true && $false);
var_dump($rt2 = $true and $false);
参考资料:
PHP Operator Precedence
PHP Logical Operators
说实话,我真的想买车了。
上班,没车,天天挤公交又特别累。晚上回家吧,还是乘地铁。那叫一个累啊。。。
如果有了车,那上下班可以轻松很多了。所以,我就想买辆车,这样,平时或许也会方便很多
可是,相对的,问题也有一些啊:
你想想,去远的地方吧。没车真不方便 。
去近的地方吧。开车又不值得。
只是,没有车库,不方便停车。出门吧,又到处找不到一个好的停车位。
不过,想想,还是忍了。。。
这些都不是什么大问题啊。实在不行,咱还可以忍忍不开的嘛。
嗯,决定了,买,分期付款,没啥买不起的。不就是贷点款嘛。。。
各位,帮忙想个建议啥的,你说,我是买国产的永久、凤凰好还是买国外的GIANT之类的呢?这些车的优劣谁能给个评测?现在的车网、论坛啥的,这类评测都很少见啊。
前段时间在博客园上看到有介绍这款软件,试用了一下,发觉还是不错的。该软件是基于Adobe AIR框架的一个富客户端,当然了,你也可以直接在官方网站上进行试用。
官方网站的网址为:http://www.balsamiq.com/products/mockups/desktop
试用是很简单的,可以直接从菜单栏上把BUTTON进行拖放,在页面中拖放控件时,还会有XY轴的水平线进行各个控件的相对定位,可以让你控件能够整齐的显示在页面上。
手绘风格的网页原型还是很容易被用户所能接受。字体也很漂亮,对于中文的支持则需要在菜单的View下选择Use System Fonts来解决。宋体的感觉不是特别好。
在程序的右上角还有一个全屏功能,该功能激活后,会在页面上有一个很大的光标箭头,你可以用鼠标控制该箭头来对你所做的页面进行演示。
花了十分钟把我的博客的页面做了一次原型(当然是根据我现在的博客做的,稍改了一下布局,我自己也觉得这样会比较好一点吧?文章页内的)
价格为$79的软件在没有注册前是不能保存、导出的,我做的图还是用系统的Print来进行截屏的(忘了装截屏软件了)。动不动跳出的提示注册框还是让你很郁闷的。不过相对于这款软件来说,还是值得被弹两下的。
由于作者表示
进行推广可以赠送license,于是我在自己的博客上也想试试,看看能不能获取序列号,毕竟这款软件确实是值得试用。