<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                >原型模式(Prototype Pattern):與工廠模式類似,都是用來創建對象的。利用克隆來生成一個大對象,減少創建時的初始化等操作占用開銷 ## (一)為什么需要原型模式 1,有些時候,我們需要創建多個類似的大對象。如果直接通過new對象,開銷很大,而且new完還得進行重復的初始化工作。可能把初始化工作封裝起來的,但是對于系統來說,你封不封裝,初始化工作還是要執行。, 2,原型模式則不同,原型模式是先創建好一個原型對象,然后通過clone這個原型對象來創建新的對象,這樣就免去了重復的初始化工作,系統僅需內存拷貝即可。 ## (二)原型模式結構圖 ![](https://box.kancloud.cn/dbaeab4b87e444c3a4f6d2c6fbb61dbd_997x574.png) ## (三)簡單實例 如果說,我們現在正開發一個游戲,有不同的地圖,地圖大小都是一樣的,并且都有海洋,但是不同的地圖溫度不一樣。 <?php //抽象原型類 Abstract class Prototype{ abstract function __clone(); } //具體原型類 class Map extends Prototype{ public $width; public $height; public $sea; public function setAttribute(array $attributes){ foreach($attributes as $key => $val){ $this->$key = $val; } } public function __clone(){} } //海洋類.這里就不具體實現了。 class Sea{} //使用原型模式創建對象方法如下 //先創建一個原型對象 $map_prototype = new Map; $attributes = array('width'=>40,'height'=>60,'sea'=>(new Sea)); $map_prototype->setAttribute($attributes); //現在已經創建好原型對象了。如果我們要創建一個新的map對象只需要克隆一下 $new_map = clone $map_prototype; var_dump($map_prototype); var_dump($new_map); 通過上面的代碼,我們可以發現利用原型模式,只需要實例化并初始化一個地圖原型對象。以后生產一個地圖對象,都可以直接通過clone原型對象產生。省去了重新初始化的過程。 但是上面的代碼還是存在一些問題。那就是它只是一個淺拷貝,什么意思呢?map原型對象有一個屬性sea存放了一個sea對象,在調用setAttribute的時候,對象的賦值方式默認是引用。而當我們克隆map對象時,直接克隆了map的sea屬性,這就使得克隆出來的對象與原型對象的sea屬性對指向了,同一個sea對象的內存空間。如果這個時候,我們改變了克隆對象的sea屬性,那么原型對象的sea屬性也跟著改變。 這顯然是不合理的,我們想要的結果應該是深拷貝,也就是改變克隆對象的所有屬性,包括用來存放sea這種其他對象的屬性時,也不影響原型對象。 當然,講到這里你可以當我在胡說。但我還是建議你打印下原型對象和克隆對象,看一下他們的sea屬性吧,然后去好好了解一下什么叫深拷貝和淺拷貝。 ## (三)深拷貝的實現 深拷貝的實現,其實也簡單,我們只要實現Map類的克隆方法就行了。這就是我們為什么要定義一個抽象原型類的原因。我們利用抽象類,強制所有繼承的具體原型類都必須來實現這個克隆方法。改進如下: //具體原型類 class Map extends Prototype{ public $width; public $height; public $sea; public function setAttribute(array $attributes){ foreach($attributes as $key => $val){ $this->$key = $val; } } //實現克隆方法,用來實現深拷貝 public function __clone(){ $this->sea = clone $this->sea; } } 到這里原型模式就算實現了,但是我覺還可以進一步進行封裝,利用工廠模式或建造者模式的思想。 ## (四)延伸 舉個例子,如果我們在克隆這個地圖對象的同時我們還需要進行一下系統設置,或是說我們想給原型對象的clone_id屬性賦值當前已經拷貝了多少個對象的總數量? 我們可以把clone這個動作封裝到一個類似的工廠方法里面去,簡單地實現一下,雖然不咋嚴謹。 <?php //抽象原型類 Abstract class Prototype{ abstract function __clone(); } //具體原型類 class Map extends Prototype{ public $clone_id=0; public $width; public $height; public $sea; public function setAttribute(array $attributes){ foreach($attributes as $key => $val){ $this->$key = $val; } } //實現克隆方法,用來實現深拷貝 public function __clone(){ $this->sea = clone $this->sea; } } //海洋類.這里就不具體實現了。 class Sea{} //克隆機器 class CloneTool{ static function clone($instance,$id){ $instance->clone_id ++; system_write(get_class($instance)); return clone $instance; } } //系統通知函數 function system_write($class){ echo "有人使用克隆機器克隆了一個{$class}對象".PHP_EOL; } //使用原型模式創建對象方法如下 //先創建一個原型對象 $map_prototype = new Map; $attributes = array('width'=>40,'height'=>60,'sea'=>(new Sea)); $map_prototype->setAttribute($attributes); //現在已經創建好原型對象了。如果我們要創建一個新的map對象只需要克隆一下 $new_map = CloneTool::clone($map_prototype,1); var_dump($map_prototype); var_dump($new_map); ## (五)模型應用 多用于創建大對象,或初始化繁瑣的對象。如游戲中的背景,地圖。web中的畫布等等
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看