#原型模式(Prototype pattern)
##簡介
原型模式是創建型模式的一種,其特點在于通過「復制」一個已經存在的實例來返回新的實例,而不是新建實例。被復制的實例就是我們所稱的「原型」,這個原型是可定制的。
***原型模式多用于創建復雜的或者耗時的實例,因為這種情況下,復制一個已經存在的實例使程序運行更高效;或者創建值相等,只是命名不一樣的同類數據。***
***
Prototype原型模式是一種創建型設計模式,它主要面對的問題是:“某些結構復雜的對象”的創建工作;由于需求的變化,這些對象經常面臨著劇烈的變化,但是他們卻擁有比較穩定一致的接口。下面我們先來看下關聯的的幾種設計模式,予以區分,再來說說原型模式。
* Singleton單件模式解決的問題是:實體對象個數問題(這個現在還不太容易混)
* AbstractFactory抽象工廠模式解決的問題是:“一系列互相依賴的對象”的創建工作
* Builder生成器模式解決的問題是:“一些復雜對象”的創建工作,子對象變化較頻繁,對算法相對穩定
* FactoryMethor工廠方法模式解決的問題是:某個對象的創建工作。
《設計模式》中說道:使用原型實例指定創建對象的種類,然后通過拷貝這些原型來創建新的對象。
##例子
```
/** Prototype Class **/
public class Cookie implements Cloneable {
public Object clone() throws CloneNotSupportedException
{
//In an actual implementation of this pattern you would now attach references to
//the expensive to produce parts from the copies that are held inside the prototype.
return (Cookie) super.clone();
}
}
/** Concrete Prototypes to clone **/
public class CoconutCookie extends Cookie { }
/** Client Class**/
public class CookieMachine
{
private Cookie cookie;//cookie必須是可復制的
public CookieMachine(Cookie cookie) {
this.cookie = cookie;
}
public Cookie makeCookie()
{
try
{
return (Cookie) cookie.clone();
} catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
return null;
}
public static void main(String args[]){
Cookie tempCookie = null;
Cookie prot = new CoconutCookie();
CookieMachine cm = new CookieMachine(prot); //設置原型
for(int i=0; i<100; i++)
tempCookie = cm.makeCookie();//通過復制原型返回多個cookie
}
}
```
現在我們再來看看原型模式的幾個要點:
* Prototype模式同樣用于隔離類對象的使用者和具體類型(易變類)之間的耦合關系,它同樣要求這些“易變類”擁有“穩定的接口”。
* Prototype模式對于“如何創建易變類的實體對象”采用“原型克隆”的方法來實現,它使得我們可以非常靈活地動態創建“擁有某些穩定接口”的新對象——所需工作僅僅是注冊一個新類的對象(即原型),然后在任何需要的地方不斷地Clone。
* Prototype模式中的Clone方法可以利用Object類的MemberwiseClone()或者序列化來實現深拷貝。
***
###Javascript中的prototype就是使用了原型模式
```
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
// 通過原型模式來添加所有實例共享的方法
// sayName() 方法將會被Person的所有實例共享,而避免了重復創建
Person.prototype.sayName = function () {
console.log(this.name);
};
var person1 = new Person('Weiwei', 27, 'Student');
var person2 = new Person('Lily', 25, 'Doctor');
console.log(person1.sayName === person2.sayName); // true
person1.sayName(); // Weiwei
person2.sayName(); // Lily
```
正如上面的代碼所示,通過原型模式定義的方法sayName()為所有的實例所共享。也就是, person1和person2訪問的是同一個sayName()函數。同樣的,公共屬性也可以使用原型模式進行定義。例如:
```
function Chinese (name) {
this.name = name;
}
Chinese.prototype.country = 'China'; // 公共屬性,所有實例共享
```
由于所有的實例對象共享同一個prototype對象,那么從外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像"繼承"了prototype對象一樣。它是淺拷貝。
//TODO clone的原理()
JAVA的clone()實現機制涉及到了反射、IO流操作、序列化等。