03 02 2020

原型模式

模式定义

原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。而不是使用标准的 new 方式。


原型模式的优势

适用于大对象的创建,因为创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可。

代码示例

Prototype\BookPrototype.class.php
<?php
namespace Prototype;

abstract class BookPrototype
{
    protected $title;
    protected $category;

    abstract public function __clone();

    public function getTitle()
    {
        return $this->title;
    }

    public function setTitle($title)
    {
        $this->title = $title;
    }

    public function getCategory()
    {
        return $this->category;
    }
}


Prototype\BarBookPrototype.class.php
<?php
namespace Prototype;

class BarBookPrototype extends BookPrototype
{
    protected $category = "Bar";

    public function __clone()
    {

    }
}


Prototype\FooBookPrototype.class.php
<?php
namespace Prototype;

class FooBookPrototype extends BookPrototype
{
    protected $category = "Foo";

    public function __clone()
    {
    }
}


Prototype\PrototypeTest.php
<?php
spl_autoload_register(function ($className){
    $className = str_replace("\\", "/", $className);
    include $className.".class.php";
});

use Prototype\BarBookPrototype;
use Prototype\FooBookPrototype;

$barBookPrototype = new BarBookPrototype();
$fooBookPrototype = new FooBookPrototype();

$barBookPrototype1 = clone $barBookPrototype;
$fooBookPrototype1 = clone $fooBookPrototype;

$barBookPrototype1->setTitle($barBookPrototype->getCategory()."Book");
$fooBookPrototype1->setTitle($barBookPrototype->getCategory()."Book");

echo $barBookPrototype->getTitle() . "\n";
echo $barBookPrototype->getCategory() . "\n";
echo $fooBookPrototype->getTitle() . "\n";
echo $fooBookPrototype->getCategory() . "\n";
echo $barBookPrototype1->getTitle() . "\n";
echo $barBookPrototype1->getCategory() . "\n";
echo $fooBookPrototype1->getTitle() . "\n";
echo $fooBookPrototype1->getCategory() . "\n";


测试示例:

php Prototype/PrototypeTest.php

输出:
 
Bar

Foo
BarBook
Bar
BarBook
Foo


总结

以下的几个场景,可能使用原型模式更简单、效率更高:

如果说我们的对象类型不是刚开始就能确定,而是在运行时确定的话,那么我们通过这个类型的对象克隆出一个新的类型更容易。

有的时候我们可能在实际的项目中需要一个对象在某个状态下的副本,这个前提很重要,这点怎么理解呢,例如有的时候我们需要对比一个对象经过处理后的状态和处理前的状态是否发生过改变,可能我们就需要在执行某段处理之前,克隆这个对象此时状态的副本,然后等执行后的状态进行相应的对比,这样的应用在项目中也是经常会出现的。

当我们处理的对象比较简单,并且对象之间的区别很小,可能只是很固定的几个属性不同的时候,使用原型模式更合适。




代码地址:https://github.com/798256478/design-patterns/tree/master/Prototype