创建工厂来简化对象的创建过程
让我们为Color类增加一个工厂
,使得建立新的实例更简单
。增加一个可以命名颜色的方法
,这样就可以不记颜色数值,只需要记住自己喜欢的颜色名字
。 工厂对象或函数不一定都要被命名为“工厂”。当你读代码时,工厂是显而易见的。相反的,它的名字最好取得有意义,这样可以反映出它解决了什么问题。
在这个代码例子中,我要叫它CrayonBox颜色工厂。静态的方法CrayonBox::getColor()引入命名颜色的字符串后,返回一个带有相应颜色属性的Color类。
下面的例子就可以测试这一点:
functionTestGetColor(){
$this->assertIsA($o=&CrayonBox::getColor(‘red’),‘Color’);
$this->assertEqual(‘#FF0000’,$o->getRgb());
$this->assertIsA($o=&CrayonBox::getColor(‘LIME’),‘Color’);
$this->assertEqual(‘#00FF00’,$o->getRgb());
}
通过这个测试,我们发现每个返回的对象都是一个实例化的Color类,getRgb()方法也返回了正确的结果。第一种情况是以“red”都是小写测试,第二种情况是以“LIME”都是大写测试,这样可以测试代码的通用性。
保险起见,我们再对其进行另外的测试,探究那些不合法的边界情况。TestBadColor()方法的作用是:用一个不存在的颜色名字引发一个包含这个颜色名字的php错误,并返回黑色。
functionTestBadColor(){
$this->assertIsA($o=&CrayonBox::getColor(‘Lemon’),‘Color’);
$this->assertErrorPattern(‘/lemon/i’);
//gotblackinstead
$this->assertEqual(‘#000000’,$o->getRgb());
}
以下是一个可以满足测试的CrayonBox类:
classCrayonBox{
/**
*Returnvalidcolorsascolorname=>array(red,green,blue)
*
*Notethearrayisreturnedfromfunctioncall
*becausewewanttohavegetColorabletobecalledstatically
*sowecan’thaveinstancevariablestostorethearray
*@returnarray
*/
functioncolorList(){
returnarray(
‘black’=>array(0,0,0)
,’green’=>array(0,128,0)
//therestofthecolors...
,’aqua’=>array(0,255,255)
);
}
/**
*FactorymethodtoreturnaColor
*@paramstring$color_namethenameofthedesiredcolor
*@returnColor
*/
function&getColor($color_name){
$color_name=strtolower($color_name);
if(array_key_exists($color_name,
$colors=CrayonBox::colorList())){
$color=$colors[$color_name];
returnnewColor($color[0],$color[1],$color[2]);
}
trigger_error(“Nocolor‘$color_name’available”);
//defaulttoblack
returnnewColor;
}
这显然地是一个非常简单的工厂,它确实制造了单一化的对象(使用了颜色名字,而不是RGB数值),它展示了在新的对象被调用之前,是如何建立一个内部对象的。