php设计模式之一工厂模式--原型模式

最近在学习设计模式,很多地方还理解的不够。在这里记录一下自己学习的东西,方便自己以后查看和理解,同时也给正在学这部分的同学提供一点参考。

概念理解:与工厂模式类似,都是用来创建对象的。利用克隆来生成一个大对象,减少创建时的初始化等操作占用开销。

主要角色:

  Prototype(抽象原型角色):声明一个克隆自身的接口

  Concrete Prototype(具体原型角色):实现一个克隆自身的操作


为什么需要原型模式
  1,有些时候,我们需要创建多个类似的大对象。如果直接通过new对象,开销很大,而且new完还得进行重复的初始化工作。可能把初始化工作封装起来的,但是对于系统来说,你封不封装,初始化工作还是要执行。,
  2,原型模式则不同,原型模式是先创建好一个原型对象,然后通过clone这个原型对象来创建新的对象,这样就免去了重复的初始化工作,系统仅需内存拷贝即可。

interface Prototype
{
    public function shallowCopy();
    public function deepCopy();
}

class ConcretePrototype implements Prototype
{
    private $_name;
    public function __construct($name)
    {
        $this->_name = $name;
    }
    
    public function setName($name)
    {
        $this->_name = $name;
    }
    public function getName()
    {
        return $this->_name;
    }
    /**
     * 浅拷贝
     * */
    public function shallowCopy()
    {
        
        return clone $this;
        
    }
    /**
     * 深拷贝
     * */
    public function deepCopy()
    {
        $serialize_obj = serialize($this);
        $clone_obj = unserialize($serialize_obj);
        return $clone_obj;
    }
}


class Demo
{
    public $string;
}
class UsePrototype
{
    public function shallow()
    {
        $demo = new Demo();
        $demo->string = "susan";
        $object_shallow_first = new ConcretePrototype($demo);
        $object_shallow_second = $object_shallow_first->shallowCopy();
        
        var_dump($object_shallow_first->getName());
        echo '<br/>';
        var_dump($object_shallow_second->getName());
        echo '<br/>';
        
        $demo->string = "sacha";
        var_dump($object_shallow_first->getName());
        echo '<br/>';
        var_dump($object_shallow_second->getName());
        echo '<br/>';
        
    }
    
    public function deep()
    {
        $demo = new Demo();
        $demo->string = "Siri";
        $object_deep_first = new ConcretePrototype($demo);
        $object_deep_second = $object_deep_first->deepCopy();
    
        var_dump($object_deep_first->getName());
        echo '<br/>';
        var_dump($object_deep_second->getName());
        echo '<br/>';
    
        $demo->string = "Demo";
        var_dump($object_deep_first->getName());
        echo '<br/>';
        var_dump($object_deep_second->getName());
        echo '<br/>';
    
    }
    
}

$up = new UsePrototype;
$up->shallow();
echo '<hr>';
$up->deep();

结果

object(Demo)[2]
  public 'string' => string 'susan' (length=5)

object(Demo)[2]
  public 'string' => string 'susan' (length=5)

object(Demo)[2]
  public 'string' => string 'sacha' (length=5)

object(Demo)[2]
  public 'string' => string 'sacha' (length=5)

object(Demo)[4]
  public 'string' => string 'Siri' (length=4)

object(Demo)[5]
  public 'string' => string 'Siri' (length=4)

object(Demo)[4]
  public 'string' => string 'Demo' (length=4)

object(Demo)[5]
  public 'string' => string 'Siri' (length=4)

原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是用对象内部提供的克隆方法,通过该方法返回一个对象的副本,这种创建对象的方式,相比我们之前说的几类创建型模式还是有区别的,之前的讲述的工厂方法模式与抽象工厂都是通过工厂封装具体的 new 操作的过程,返回一个新的对象,有的时候我们通过这样的创建工厂创建对象不值得,特别是以下的几个场景,可能使用原型模式更简单、效率更高:

   有的时候我们可能在实际的项目中需要一个对象在某个状态下的副本,这个前提很重要,这点怎么理解呢,例如有的时候我们需要对比一个对象经过处理后的状态和处理前的状态是否发生过改变,可能我们就需要在执行某段处理之前,克隆这个对象此时状态的副本,然后等执行后的状态进行相应的对比,这样的应用在项目中也是经常会出现的。
  当我们处理的对象比较简单,并且对象之间的区别很小,可能只是很固定的几个属性不同的时候,使用原型模式更合适。

posted @ 2017-10-24 15:01  CandyChen  阅读(118)  评论(0)    收藏  举报