关于php:PHP设计模式之原型模式

45次阅读

共计 3673 个字符,预计需要花费 10 分钟才能阅读完成。

原型模式其实更形象的来说应该叫克隆模式。它次要的行为是对对象进行克隆,然而又把被克隆的对象称之为最后的原型,于是,这个模式就这样被命名了。说真的,从应用形式来看真的感觉叫克隆模式更贴切一些。

Gof 类图及解释

GoF 定义:用原型实例指定创建对象的品种,并且通过拷贝这些原型创立新的对象

GoF 类图

代码实现

abstract class Prototype
{
    public $v = 'clone' . PHP_EOL;

    public function __construct()
    {echo 'create' . PHP_EOL;}

    abstract public function __clone();}

首先咱们通过模仿的形式定义了一个原型,这里次要是模仿了__clone()这个办法。其实这是 PHP 自带的一个魔术办法,基本是不须要咱们去进行定义的,只须要在原型类中进行实现就能够了。当内部应用 clone 关键字进行对象克隆时,间接就会进入这个魔术办法中。在这个魔术办法外面咱们能够对属性进行解决,特地是针对援用属性进行一些独特的解决。在这个例子中,咱们只应用了一个值类型的变量。无奈体现出援用类型的问题,咱们将在前面的实例中演示对援用类型变量的解决。

class ConcretePrototype1 extends Prototype
{public function __clone()
    {}}

class ConcretePrototype2 extends Prototype
{public function __clone()
    {}}

模仿的具体实现的原型,其实就是次要去具体的实现__clone()办法。前面咱们看具体的例子时再阐明。

class Client
{public function operation()
    {$p1 = new ConcretePrototype1();
        $p2 = clone $p1;

        echo $p1->v;
        echo $p2->v;
    }
}

$c = new Client();
$c->operation();

客户端应用 clone 来复制 $p1,能够看到 $p2 也具备雷同的 $v 属性。

  • 原型模式看似就是复制了一个雷同的对象,然而请留神,复制的时候,__construct()办法并没有被调用,也就是当你运行这段代码的时候,create 只输入了一次。这也就带出了原型模式最大的一个特点——缩小创建对象时的开销
  • 基于上述特点,咱们能够疾速的复制大量雷同的对象,比方要给一个数组中塞入大量雷同的对象时。
  • 复制进去的对象中如果都是值类型的属性,咱们能够任意批改,不会对原型产生影响。而如果有援用类型的变量,则须要在__clone()办法进行一些解决,否则批改了复制对象的援用变量中的内容,会对原型对象中的内容有影响。

咱们的手机操作系统(也能够设想一下 PC 电脑的操作系统),都是怎么装置到设施中呢?其实都是不停的复制拷贝最后的那一套零碎。用微软的例子十分好阐明这个问题,当年微软可能成为一个帝国,其实也是因为他不停的将 winodws 操作系统拷贝复制到光盘中,而后卖给千家万户(当然,这里没中国什么事儿)。而中国市场呢,大量的高手破解了 windows 之后也是由这一份文件不停的复制拷贝才装到了咱们的电脑中。手机、智能设施等各类产品的操作系统、软件都是如此。一次开发有限拷贝正是软件行业暴利的起因。毕竟咱们的零碎也是由不少的工程师日以继夜的 996 在 Android 原生零碎的根底上开发进去的,连忙一直的复制到行将出厂的手机上吧!!

残缺代码: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

<?php
interface ServiceProvicer
{public function getSystem();
}

class ChinaMobile implements ServiceProvicer
{
    public $system;
    public function getSystem(){return "中国移动" . $this->system;}
}
class ChinaUnicom implements ServiceProvicer
{
    public $system;
    public function getSystem(){return "中国联通" . $this->system;}
}

class Phone 
{
    public $service_province;
    public $cpu;
    public $rom;
}

class CMPhone extends Phone
{function __clone()
    {// $this->service_province = new ChinaMobile();
    }
}

class CUPhone extends Phone
{function __clone()
    {$this->service_province = new ChinaUnicom();
    }
}


$cmPhone = new CMPhone();
$cmPhone->cpu = "1.4G";
$cmPhone->rom = "64G";
$cmPhone->service_province = new ChinaMobile();
$cmPhone->service_province->system = 'TD-CDMA';
$cmPhone1 = clone $cmPhone;
$cmPhone1->service_province->system = 'TD-CDMA1';

var_dump($cmPhone);
var_dump($cmPhone1);
echo $cmPhone->service_province->getSystem();
echo $cmPhone1->service_province->getSystem();


$cuPhone = new CUPhone();
$cuPhone->cpu = "1.4G";
$cuPhone->rom = "64G";
$cuPhone->service_province = new ChinaUnicom();
$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();

阐明

  • 打印了很多货色呀,不过次要的还是看看挪动手机,也就是 CMPhone 中的__clone()办法,咱们没有从新去初始化一个新对象。这时,复制的 $cmPhone1 对象中的 service_province 和 $cmPhone 中的是同一个对象。没错,这就是援用的复制问题。援用只是复制了援用的地址,他们指向的是同一个对象。当 $cmPhone1 批改 service_province 对象外面的属性内容时,$cmPhone 外面的 service_province 对象外面的属性也跟着扭转了。
  • 在 CUPhone 中,咱们从新 new 了一个新的 service_province 对象。这次里面的 $cuPhone1 对该对象中的属性批改时就不会影响 $cuPhone 中援用对象的值。
  • 原型模式中最次要的就是要留神上述两点,而一般的值属性会间接进行复制,不会产生这个问题。这里又关涉出另外两个概念:浅复制 深复制
  • 浅复制,是指被复制对象的所有变量都含有与原来对象雷同的值,而所有的对其余对象的援用都依然指向原来的对象
  • 深复制把援用对象的变量指向复制过的新对象,而不是原有的被援用的对象
  • 对于援用和值的问题,咱们将在其余的文章中进行解说,请关注微信或掘金号

下期看点

原型模式尽管平时用得不多,然而学习之后发现还真是挺有用的,特地是须要大量的反复对象时,能够大大节约新建对象的资源需要,当前还是须要多多练习早日利用在理论的业务场景中。下一个又会是谁呢?别急别急,先去下个馆子,厨师、服务员、顾客,这三个因素就能组成一个神奇的模式:命令模式

各自媒体平台均可搜寻【硬核项目经理】

正文完
 0