开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第三阶段:工厂模式】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/713/detail/12720
工厂模式
内容简介
一、什么是工厂模式
二、使用工厂模式的步骤
三、使用工厂模式示例
四、小结
一、什么是工厂模式
Factory,是指像工厂一样流水线生产对象,由一个地方生产对象,其他位置就不需要额外实例化对象,从而可以方便后期代码统一的维护。那么,工厂模式是用于代生产对象,指工厂专门有一个类,叫工厂类,专门负责生产对象,其他地方不再负责实例化等。工厂模式下可以方便隐藏真实的类结构,就是类到底如何产生的,怎么能够实例化得到对象或单例,因此更加安全。工厂模式不需要关注工厂是如何产生对象,只需让工厂产生对象。工厂模式的本质就是让外部提供对象。
二、使用工厂模式的步骤
一是创建不同类,二是创建生产对象的工厂类,工厂类负责生产对象,以后使用对象不允许直接调用具体类,只能允许工厂类实现,三是调用工厂类生产对象。
三、使用工厂模式示例
第一:工厂模式针对的是“相同模型“的统一产出(不能生产手机的去生产汽车),即使用工厂模式产出对象对应的类都有相同的结构或者功能。所以,首先要有一批具有类似功能的类。(其本质是同样的大类下的小类)
示例如下:
下面有三类:man类,woman类和ladyboy类
#三个类文件
#人是一种大类,人下应该有男人、女人、人妖,各自成类
class Man{
public function display(){
echo '这是男人
’;
}
Class Woman{
public function display(){
echo '这是女人
’;
}
}
class Ladyboy{
public function display(){
echo '这是 人妖
';
}
第二:不实例化,使用工厂模式就需要增加一个工厂类:HumanFactory ,专门用来产生类。
给提供一个类名 return new $classmate() 后帮忙产生,至于产生几个则是在代码中控制。
代码为
class HumanFactory{
public function getInstance($classname){
return new $classname();
}
}
$hf=new HumFactory();
$m= $hf->getInstance(‘Man’):
$m->display();
$m= Shf-›getInstance(‘woman’);
$w->display();
具体操作如下图:
首先要产生一个类,类具有相似性。
下一步需要产生工厂类(一定要明确工厂是干什么的)
Class humanfactory{
然后需要提供产生对象的方法:
Public function getinstance($classname){
(因为要知道产生什么类的对象,所以要在getinstance()上填上类别getinstance($classname)
最后负责产生对象:
Return new $classname();
如果此时需要使用则需要使用:
$h=new humanfactory();
$m= $hf->getInstance(‘Man’);
$m->display();
如果想要女人则在$m= $hf->getInstance(‘Man’):中将man换
成woman
这样就有一个工厂,外部不用管怎么去产生对象,只要得到类名,它就会通过工厂来得到对象。
第三:上述工厂类在对象生产的时候,额外产生了一个工厂类的对象
$hf=new HumFactory();该对象无实际意义,因此可以使用更优的方
式来生产对象:静态工厂。
静态工厂:public static function getinstance($classname)
静态工厂优化时要注意同名后需要注释普通方法的,内容不变,调用方式变为$m=Humanfactory::getInstance(‘Man’);
也可以在其中增加安全控制:
If(!class_exists($classname))
,内存里有才产生,否则return false;
比如var_dump(HumanFactory::getInstance(‘Human’)); ,没有这个类,所以bool(false)。
有了这个措施,可以统一的进行安全维护,这就是它的便捷性。所以工厂类不能帮我们节省代码,但是它可以为我们后续的操作,后续的扩充,补充以及安全检查带来很大的方便。
第四:以上模式虽然也是工厂生产对象,但是是建立在使用者知道类名的前提下,而且如果原类名修改,依然需要多处修改代码,所以没有达到工厂模式的真实目的。为了方便修改,我们可以修改工厂模式,让用户只需传一个标志flag即可,而内部根据这个标志来得到不同类的对象自己判定。
class HumanFactory{
public static function getInstance($flag){
# flag只是一种标志:不是类名
# $flag可以是m代表Man, w代表woman, L代表Ladyboy
switch($flag) (
case 'm':
return new Man() ;
case 'w’:
return new Woman();
case 'L':
return new. Ladyboy();
default:
return nu11;
# 匹配失败,返回空
}
}
}
$m = Humanf actory: :getInstanceC'm');
$m->disp1ay();
#这是男人
$w = HumanFactory: :getInstance('w');
$w->disp1ay();
#这是女人
应用改为:
$m=humanfactory::getinstance();
Var_dump($m);
如图,getinstance里为l,则可以得到ladyboy。
所以这样我们就得到一个用标志来简化我们的类。
如果以后需要修改,就只需在 return new 中修改对应名字即可,外部代码的调用不需要改变。
四、小结
1、工厂模式是一种按需生产对象的模式(一个工厂生产的对象一个相似)。
2、工厂模式通常是需要在大型项目中,会出现很多的相同功能的类,此时可以使用工厂产生对象。
3、工厂模式的优点是方便后期对类的维护(更名)。
4、工厂模式的缺点是随着功能的增加,会增加很多开发量(开发多个工厂),增加开发难度,但是会方便后期维护,主要用于大型项目。而且工厂可以去匹配单例,保证我们里面每一个类的对象它只能产生一个对象。以上只是一种简单工厂模式,复杂的工厂模式会有不同的工厂,甚至会有抽象工厂,就是工厂类会有副类-抽象类,抽象类规范了真正生产类的一些方式,而子类只是去呈写这样的方式,调用时需要使用不同工厂来实现对象生产。