当前位置: 首页 > 后端技术 > PHP

PHP设计模式原型模式

时间:2023-03-30 01:42:51 PHP

原型模式更形象的应该叫克隆模式。它的主要行为是克隆对象,但它也将克隆的对象称为原始原型,所以这种模式是这样命名的。说实话,从使用的角度来说,我真的觉得克隆模式更合适。Gof类图及解释GoF定义:用原型实例指定要创建的对象类型,通过复制这些原型创建新对象GoF类图代码实现abstractclassPrototype{public$v='clone'.PHP_EOL;公共功能__construct(){echo'创建'.PHP_EOL;}abstractpublicfunction__clone();}首先我们通过模拟的方式定义一个原型,这里主要模拟__clone()的方法。其实这是PHP自带的一个神奇方法。我们根本不需要定义它。我们只需要在原型类中实现即可。当外部使用clone关键字进行对象克隆时,会直接进入这个魔术方法。在这个神奇的方法中,我们可以对属性进行处理,尤其是对引用属性的一些特有的处理。在这个例子中,我们只使用了一个值类型的变量。无法体现引用类型的问题,我们将在后面的例子中演示对引用类型变量的处理。classConcretePrototype1extendsPrototype{publicfunction__clone(){}}classConcretePrototype2extendsPrototype{publicfunction__clone(){}}具体实现模拟的原型其实就是具体实现__clone()方法。后面我们看具体例子的时候再解释。classClient{publicfunctionoperation(){$p1=newConcretePrototype1();$p2=克隆$p1;回声$p1->v;回声$p2->v;}}$c=newClient();$c->operation();客户端使用clone复制$p1,可以看到$p2也有相同的$v属性。prototype模式看起来是复制同一个对象,但是请注意,复制的时候并没有调用__construct()方法,也就是说,运行这段代码时,只创建一次outputs。这也带出了原型模式最大的特点之一——减少了创建对象的开销。基于以上特点,我们可以快速复制大量相同的对象,例如当我们想将大量相同的对象塞入数组时。如果复制的对象都是值类型的属性,我们可以任意修改,不影响原型。而如果有引用类型的变量,则需要在__clone()方法中做一些处理,否则,修改复制对象的引用变量中的内容,会影响原型对象中的内容。我们的手机操作系统(你也可以想象PC电脑的操作系统)是怎么安装在设备上的呢?事实上,他们是在不断地复制原来的系统。微软的例子很好的说明了这个问题。其实当时的微软之所以能够成为一个帝国,就是因为它不停地把winodws操作系统拷贝成光盘,然后卖到千家万户(当然,中国这边也无可厚非)。至于中国市场,经过大量高手破解windows后,就是这个文件被不断复制安装到我们的电脑中。手机、智能设备等各类产品的操作系统和软件也是如此。一个开发的无限副本是软件行业暴利的原因。毕竟我们的系统也是众多工程师在996夜以继日的在Android原生系统的基础上开发的,所以赶快copy到即将出厂的手机上吧!!完整代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/08.prototype/source/prototype.php示例也是基于手机端的,这次我们根据不同的需求经营者要开发一批定制机,即包装机。老实说,这些手机之间没有区别。大部分配置相同,只是承载系统不同,偶尔会出现部分机型CPU和内存的差异。这时候我们可以使用原型模式快速复制,只修改一些不一样的地方。原型机类图完整源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/08.prototype/source/prototype-phone.php系统;}}class中国联通实现ServiceProvicer{public$system;publicfunctiongetSystem(){return"中国联通".$这个->系统;}}classPhone{public$service_province;公共$cpu;public$rom;}classCMPhoneextendsPhone{function__clone(){//$this->service_province=newChinaMobile();}}classCUPhoneextendsPhone{function__clone(){$this->service_province=newChinaUnicom();}}$cmPhone=newCMPhone();$cmPhone->cpu="1.4G";$cmPhone->rom="64G";$cmPhone->service_province=newChinaMobile();$cmPhone->service_province->system='TD-CDMA';$cmPhone1=克隆$cmPhone;$cmPhone1->service_province->system='TD-CDMA1';var_dump($cmPhone);var_dump($cmPhone1);echo$cmPhone->service_province->getSystem();echo$cmPhone1->service_province->getSystem();$cuPhone=newCUPhone();$cuPhone->cpu="1.4G";$cuPhone->rom="64G";$cuPhone->service_province=newChinaUnicom();$cuPhone->service_province->system='WCDMA';$cuPhone1=clone$cuPhone;$cuPhone1->rom="128G";$cuPhone1->service_province->system='WCDMA1';var_dump($cuPhone);var_dump($cuPhone1);echo$cuPhone->service_province->getSystem();echo$cuPhone1->service_province->getSystem();说明打印了很多东西,但是主要还是看手机,就是__clone()方法,我们没有重新初始化一个新的对象。此时复制的$cmPhone1对象中的service_province和$cmPhone是同一个对象。没错,这就是引用的复制问题。引用只是复制引用的地址,它们指向同一个对象。当$cmPhone1修改service_province对象中的属性内容时,$cmPhone中的service_province对象中的属性也会随之改变。在CUPhone中,我们更新了一个新的service_province对象。这次$cuPhone1在外面修改对象的属性时,不会影响到$cuPhone中引用对象的值。原型模式最重要的就是要注意以上两点,普通的值属性会直接复制,不会出现这个问题。这里涉及另外两个概念:浅拷贝和深拷贝。浅拷贝是指被复制对象的所有变量都包含与原对象相同的值,所有对其他对象的引用仍然指向原对象。深拷贝将被引用对象的变量指向复制的新对象,而不是原来的被引用对象。关于references和values的问题我们会在其他文章中说明。下期请关注微信或掘金。原型模式虽然我平时用的不多,但是学了之后发现真的很好用,尤其是在需要大量重复对象的时候,可以大大节省新对象的资源需求。以后还是要多多实践,尽快应用到实际的业务场景中。下一个会是谁?别着急,别着急,先去下一家餐厅,厨师,服务员,顾客,这三个元素可以组成一个神奇的模型:指挥模式在各个媒体平台都可以搜索【硬核项目经理】