1. 程式人生 > >設計模式(四)原型模式Prototype(建立型)

設計模式(四)原型模式Prototype(建立型)

1.   概述

我們都知道,建立型模式一般是用來建立一個新的物件,然後我們使用這個物件完成一些物件的操作,我們通過原型模式可以快速的建立一個物件而不需要提供專門的new()操作就可以快速完成物件的建立,這無疑是一種非常有效的方式,快速的建立一個新的物件。

例子1:孫悟空拔下一嘬猴毛,輕輕一吹就會變出好多的孫悟空來。

例子2:寄個快遞
下面是一個郵寄快遞的場景:
“給我寄個快遞。”顧客說。
“寄往什麼地方?寄給……?”你問。
“和上次差不多一樣,只是郵寄給另外一個地址,這裡是郵寄地址……”顧客一邊說一邊把寫有郵寄地址的紙條給你。
“好!”你愉快地答應,因為你儲存了使用者的以前郵寄資訊,只要複製這些資料,然後通過簡單的修改就可以快速地建立新的快遞資料了。


2. 問題

當物件的建構函式非常複雜,在生成新物件的時候非常耗時間、耗資源的情況?我們是怎麼來建立呢?

3. 解決方案

       通過複製(克隆、拷貝)一個指定型別的物件來建立更多同類型的物件。這個指定的物件可被稱為“原型”物件,也就是通過複製原型物件來得到更多同類型的物件。即原型設計模式。在php的很多模板庫,都用到clone。如smarty等。

4. 適用性

原型模式的主要思想是基於現有的物件克隆一個新的物件出來,一般是有物件的內部提供克隆的方法,通過該方法返回一個物件的副本,這種建立對象的方式,相比我們之前說的幾類建立型模式還是有區別的,之前的講述的工廠模式與抽象工廠都是通過工廠封裝具體的new操作的過程,返回一個新的對

象,有的時候我們通過這樣的建立工廠建立物件不值得,特別是以下的幾個場景的時候,可能使用原型模式更簡單也效率更高。

• 1)當一個系統應該獨立於它的產品建立、構成和表示時,要使用 Prototype模式

• 2)當要例項化的類是在執行時刻指定時,例如,通過動態裝載;

• 3)為了避免建立一個與產品類層次平行的工廠類層次時

• 4)當一個類的例項只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工例項化該類更方便一些。(也就是當我們在處理一些物件比較簡單,並且物件之間的區別很小,可能只是很固定的幾個屬性不同的時候,可能我們使用原型模式更合適)。

5. 結構

     原型模式結構如下頁上圖所示:        

6. 組成

客戶(Client)角色:使用原型物件的客戶程式
抽象原型(Prototype)角色:規定了具體原型物件必須實現的介面(如果要提供深拷貝,則必須具有實現clone的規定)

具體原型(ConcretePrototype):從抽象原型派生而來,是客戶程式使用的物件,即被複制的物件。此角色需要實現抽象原型角色所要求的介面。

7. 效果

Prototype模式有許多和Abstract Factory模式 和 Builder模式一樣的效果:它對客戶隱藏了具體的產品類,因此減少了客戶知道的名字的數目。此外,這些模式使客戶無需改變即可使用與特定應用相關的類。
下面列出Prototype模式的另外一些優點。
1 ) 執行時刻增加和刪除產品: Prototype允許只通過客戶註冊原型例項就可以將一個新的具體產品類併入系統。它比其他建立型模式更為靈活,因為客戶可以在執行時刻建立和刪除原型。
2 ) 改變值以指定新物件: 高度動態的系統允許你通過物件複合定義新的行為—例如,通過為一個物件變數指定值—並且不定義新的類。你通過例項化已有類並且將這些例項註冊為客戶物件的原型,就可以有效定義新類別的物件。客戶可以將職責代理給原型,從而表現出新的行為。這種設計使得使用者無需程式設計即可定義新“類” 。實際上,克隆一個原型類似於例項化一個類。Prototype模式可以極大的減少系統所需要的類的數目。
3) 改變結構以指定新物件:許多應用由部件和子部件來建立物件。
4) 減少子類的構造 Factory Method 經常產生一個與產品類層次平行的 Creator類層次。Prototype模式使得你克隆一個原型而不是請求一個工廠方法去產生一個新的物件。因此你根本不需要Creator類層次。這一優點主要適用於像 C + +這樣不將類作為一級類物件的語言。像Smalltalk和Objective C這樣的語言從中獲益較少,因為你總是可以用一個類物件作為生成者。在這些語言中,類物件已經起到原型一樣的作用了。
5) 用類動態配置應用 一些執行時刻環境允許你動態將類裝載到應用中。在像 C + +這樣的語言中,Prototype模式是利用這種功能的關鍵。一個希望建立動態載入類的例項的應用不能靜態引用類的構造器。而應該由執行環境在載入時自動建立每個類的例項,並用原型管理器來註冊這個例項(參見實現一節) 。這樣應用就可以向原型管理器請求新裝載的類的例項,這些類原本並沒有和程式相連線。 E T + +應用框架[ W G M 8 8 ]有一個執行系統就是使用這一方案的。
Prototype的主要缺陷是每一個Prototype的子類都必須實現clone操作,這可能很困難。 如,當所考慮的類已經存在時就難以新增 clone操作。當內部包括一些不支援拷貝或有迴圈引用的物件時,實現克隆可能也會很困難的。
8. 實現
<?php
/**
 * 原型模式 
 */
 
/**
 * 抽象原型角色
 */
interface Prototype {
    public function copy();
}
 
/**
 * 具體原型角色
 */
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 copy() {
       /** 深拷貝 */
       return  clone  $this;    
       /** 淺拷貝 */
       //return  $this;   
    }
}

 
class Client {
 
     /**
     * Main program.
     */
    public static function main() {
        $object1 = new ConcretePrototype(11);
        $object_copy = $object1->copy();

        var_dump($object1->getName());
        echo '<br />';
        var_dump($object_copy->getName());
        echo '<br />';
 
        $object1->setName(22);
        var_dump($object1->getName());
        echo '<br />';
        var_dump($object_copy->getName());
        echo '<br />';
    }
}
 
Client::main();
?>




9. 淺拷貝和深拷貝
原型模式的原理圖:

淺拷貝 被拷貝物件的所有變數都含有與原物件相同的值,而且對其他物件的引用仍然是指向原來的物件。即淺拷貝只負責當前物件例項,對引用的物件不做拷貝。 淺複製後的物件和物件副本的情況:

深拷貝
被拷貝物件的所有的變數都含有與原來物件相同的值,除了那些引用其他物件的變數。那些引用其他物件的變數將指向一個被拷貝的新物件,而不再是原有那些被引用物件。即 深拷貝把要拷貝的物件所引用的物件也都拷貝了一次,而這種對被引用到的物件拷貝叫做間接拷貝。
深複製的物件和物件副本的情況:
深拷貝要深入到多少層,是一個不確定的問題。
在決定以深拷貝的方式拷貝一個物件的時候,必須決定對間接拷貝的物件是採取淺拷貝還是深拷貝還是繼續採用深拷貝。
因此,在採取深拷貝時,需要決定多深才算深。此外,在深拷貝的過程中,很可能會出現迴圈引用的問題。

10. 帶Prototype Manager的原型模式

原型模式的第二種形式是帶原型管理器的原型模式,其UML圖如下:

     

 原型管理器(Prototype Manager)角色:建立具體原型類的物件,並記錄每一個被建立的物件。

       下面這個例子演示了在原型管理器中儲存使用者預先定義的顏色原型,客戶通過原型管理器克隆顏色物件。

<?php
/**
 * abstract Prototype
 *
 */
abstract class ColorPrototype
{
  //Methods
	abstract function  copy();
}

/**
 * Concrete Prototype
 *
 */
class Color extends ColorPrototype{
	//Fields
	private  $red;
	private  $green;
	private  $blue;
	//Constructors
	function __construct( $red, $green, $red) {
	 	$this->red = $red;
	 	$this->green = $green;
	 	$this->blue = $red;
	 }
	 /**
	  * set red
	  *
	  * @param unknown_type $red
	  */
	public  function setRed($red) {
	 	$this->red = $red;
	 }
	 
	 /**
	  * get red
	  *
	  */
	public  function getRed(){
	 	return  $this->red;
	 }
	 /**
	  *set Green
	  *
	  * @param  $green
	  */
	public  function setGreen($green) {
	 	$this->green = $green;
	 }
	 /**
	  * get Green
	  *
	  * @return unknown
	  */
	public  function getGreen() {
	 	return  $this->green ;
	 }
	 /**
	  *set Blue
	  *
	  * @param  $Blue
   	  */
	public  function setBlue($Blue) {
	 	$this->blue = $Blue;
	}
	 /**
	  * get Blue
	  *
	  * @return unknown
	  */
	public  function getBlue() {
	 	return  $this->blue ;
	}
	
	/**
	 * Enter description here...
	 *
	 * @return unknown
	 */
	function copy(){
		return clone $this;
	}
	
	function display() {
		echo $this->red , ',', $this->green, ',', $this->blue ,'<br>';
	}
}
/**
 * Enter description here...
 *
 */
class ColorManager
{
	// Fields
	static  $colors = array();
	// Indexers
	public static function add($name, $value){
		self::$colors[$name] = $value;
	}
	
	public static function getCopy($name) {
		return   self::$colors[$name]->copy();
	}
}
/**
 *Client
 *
 */
class Client
{
	public static function  Main()
	{
		//原型:白色
		ColorManager::add("white", new Color( 255, 0, 0 ));
		
		//紅色可以由原型白色物件得到,只是重新修改白色: r
		$red = ColorManager::getCopy('white');
		$red->setRed(255);
		$red->display();
		
		//綠色可以由原型白色物件得到,只是重新修改白色: g
		$green = ColorManager::getCopy('white');
		$green->setGreen(255);
		$green->display();
		
		//綠色可以由原型白色物件得到,只是重新修改白色: b
		$Blue = ColorManager::getCopy('white');
		$Blue->setBlue(255);
		$Blue->display();
	}
}

ini_set('display_errors', 'On');
error_reporting(E_ALL & ~ E_DEPRECATED);
Client::Main();
?>


相關推薦

設計模式原型模式Prototype建立

1.   概述 我們都知道,建立型模式一般是用來建立一個新的物件,然後我們使用這個物件完成一些物件的操作,我們通過原型模式可以快速的建立一個物件而不需要提供專門的new()操作就可以快速完成物件的建立,這無疑是一種非常有效的方式,快速的建立一個新的物件。 例子1

.NET應用架構設計—面向物件分析與設計原型模式彩色建模、領域無關模型概念版

閱讀目錄: 1.背景介紹 2.問自己,UML對你來說有意義嗎?它幫助過你對系統進行分析、建模嗎? 3.一直以來其實我們被一個縫隙隔開了,使我們對OOAD遙不可及 4.四色原型模式填補這個歷史縫隙,讓我們真的看見OOAD的希望 5.在四色原型上運用彩色建模增強視覺衝擊力 6.通過四色原

淺談Java設計模式原型模式Prototype

前言: 原型模式雖然是建立型的模式,但是與工程模式沒有關係,從名字即可看出,該模式的思想就是將一個物件作為原型,對其進行復制、克隆,產生一個和原物件類似的新物件。本小結會通過物件的複製,進行講解。在Java中,複製物件是通過clone()實現的,先建立一個原型類: publ

Unity遊戲設計模式原型模式Prototype Pattern

        原型模式,顧名思義就是通過物件的原型克隆而產生的新的物件。原型模式在遊戲中運用非常多。怪物,一張地圖上有許許多多的怪物,這些怪物一般都具有共通性,同一種怪物就有可能擁有同樣的模型,同樣的攻擊方式等。即使是不同型別的怪物他們也擁有許多共通性,例如都擁有攻擊力,

C#設計模式抽象工廠模式AbstractFactory【創建

抽象 抽象工廠 album 代碼 ctf bst actor 抽象工廠模式 .cn 一、引言 寫了3篇有關設計模式的文章了,大家有了些反饋,說能從中學到一些東西,我感到很欣慰,那就繼續努力。今天我要寫第四個模式了,該模式叫抽象工廠。上一篇文章我們講了【工廠方法】模式,它是為

設計模式——原型模式

設計模式 原型模式設計模式(六)——原型模式一、原型模式簡介1、原型模式簡介 原型模式使用原型實例指定創建對象的種類,並且通過拷貝原型對象創建新的對象。 Prototype模式提供了一個通過已存在對象進行新對象創建的接口(clone), clone()實現和具體的語言相關,在C++中通過拷貝構造函

設計模式6----原型模式

cli int sets 工作原理 type vsu targe 復制 層次 簡介: Prototype原型模式是一種創建型設計模式,Prototype模式允許一個對象再創建另外一個可定制的對象,根本無需知道任何如何創建的細節,工作原理是:通過將一個原型對象傳給那個要發動創

C#設計模式6——原型模式

1.原型模式介紹   在軟體系統開發中,有時候會遇到這樣的情況:我們需要用到多個相同例項,最簡單直接的方法是通過多次呼叫new方法來建立相同的例項。如下: Person person=new Person(){Name="jack",Age=20}; Person person2=new Pers

設計模式---- 原型模式

err ack 深克隆 system not 原型模式 get bytes exception 原型模式   通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。就是 java 中的克隆技術,以某個對象為原型,復制出新的對象。顯然,新的對象具備原

設計模式---原型模式

吐槽 今天帶貓貓去打針,然後她各種皮,差點從袋子裡面跑出去了emmmmm,早上上課時候,編譯原理上上課居然就聽不懂了,很尷尬,趕緊回去補。 什麼叫原型模式 就是類似鳴人的影分身之術,可以克隆物件 定義:用原型例項指向建立物件的種類,並通過複製這些原型建立新的物件

設計模式 c++版9——原型模式

定義:用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。 示例一:個性化電子賬單 1. 需求說明: 銀行傳送電子賬單的郵件一般是有要求的:①個性化服務:發過去的郵件上總有一些個人資訊,比如姓氏等。②遞送成功率:若大批量地傳送郵件會被收房郵件伺服器誤認為是

java設計模式---4原型模式

原型模式(Prototype Pattern)是用於建立重複的物件,同時又能保證效能。用原型例項來指定建立物件的種類,然後通過clone這個原型物件來建立新物件。 先定義一個學生類Student他實現Cloneable介面並重寫了clone()方法(clone()方法是Object類中定義的

設計模式Java隨筆原型模式

原型模式(Prototype Pattern):誒呀,一種灰常簡單的模式,就是要求物件實現一個可以“克隆”自身的介面,這樣就可以通過複製一個例項物件本身來建立一個新的例項。只要實現了克隆自身的方法,就可以通過這個方法來獲取新的物件,而無須再去通過new來建立。 Specif

設計模式java- 原型模式

1. 簡介   原型模式又稱克隆模式,它允許一個物件可以創建出另一個與自身型別相同的物件。客戶不需要知道建立的細節,就可以獲取到需要的複製品。   在java中通過繼承Cloneable的介面實現原型模式,在c++中則可以通過過載賦值函式進行實現。   在實現原

C# 設計模式原型模式unity演示

1、引言   我們在軟體開發的過程中,常常會用到new欄位來建立物件。那麼是不是隻有這一種辦法來建立物件呢?答案顯然不是的。然而使用new來建立物件時,適用於任何時候呢?顯然答案也是否定的,什麼時候就不適用new呢?讓我們來看看,當我們建立的一個

設計模式 ()——簡單工廠模式Simple Factory,建立

1.概述 使用設計模式可以提高程式碼的可複用性、可擴充性和可維護性。簡單工廠模式(Simple Factory Pattern)屬於建立型模式。簡單工廠模式,由一個工廠物件決定創建出哪一種產品類的例項,它經常被用於封裝建立物件的程式碼。 簡單工廠模式類圖結構

建立設計模式5種——原型模式

建立類設計模式(5種)——原型模式 一、圖層 大家如果用過類似於Photoshop的平面設計軟體,一定都知道圖層的概念。圖層概念的提出,使得設計、圖形修改等操作更加便利。設計師既可以修改和繪製當前影象物件,又可以保留其它影象物件,邏輯清晰,且可以及時得到反饋。本節內容,將以圖層為主角,介紹原

設計模式C#——原型模式

推薦閱讀:  我的CSDN  我的部落格園  QQ群:704621321       在軟體開發過程中,我們習慣使用new

設計模式快速學習原型模式

用於建立重複的物件,同時又能保證效能。通俗的講,原型模式就是克隆物件,直接copy位元組碼,不走構造方法,效能非常高。ORM中經常用到。 注意 只支援9種資料型別的深拷貝: 8大基本型別(int long float double boolean char short byte )+String

設計模式C++實現5——原型模式、模板方法模式

       軟體領域中的設計模式為開發人員提供了一種使用專家設計經驗的有效途徑。設計模式中運用了面向物件程式語言的重要特性:封裝、繼承、多型,真正領悟設計模式的精髓是可能一個漫長的過程,需要大量實踐經驗的積累。最近看設計模式的書,對於每個模式,用C++寫了個小例子,加深一