原型模式 詳解
阿新 • • 發佈:2019-01-23
定義
用原型例項指定建立物件的種類,並通過拷貝這些原型建立新的物件;
建立型模式
淺拷貝:使用一個已知例項對新建立例項的成員變數逐個賦值;
深拷貝:當一個類的拷貝構造方法,不僅要複製物件的所有非引用成員變數值,還要為引用型別的成員變數建立新的例項,並且初始化為形式引數例項值;
角色
- 抽象原型類(Prototype):抽象原型類,宣告克隆自身的介面;
- 具體原型類(ConcretePrototype):具體原型類,實現克隆的具體操作;
- 客戶端(Client):讓一個克隆自身,從而獲得新的物件;
從網上找到的例圖
適用場景
- 當一個系統應該獨立於它的產品建立,構成和表示時,要使用Prototype模式;
- 當要例項化的類是在執行時刻指定時,比如動態載入;
- 為了避免建立一個與產品類層次平行的工廠類層次;
- 當一個類的例項只有幾個不同狀態組合中的一種時,建立相應數目的原型並克隆它們可能比每次用合適的狀態手工例項化該類更方便一些;
例子
實現程式碼
/**
* Created by George on 16/7/20.
*/
/**
* 第一種建立物件方式
* @type {{name: string, drive: Function, panic: Function}}
*/
var myCar = {
name : "Mini QQ",
drive : function () {
console.log("driving.");
},
panic : function () {
console.log("stop.");
}
};
// 通過Object的create函式例項化一個新的car
var yourCar = Object.create(myCar);
console.log(yourCar.name);
/**
* 第二種建立物件方式
* @type {{getModel: Function}}
*/
var verticle = {
getModel : function () {
console.log("the model of this vehicle is " + this.model);
}
};
// 使用create函式的第二個引數來初始化物件屬性
var car = Object.create(verticle, {
"id" : {
value : 1,
enumerable : true
},
"model" : {
value : "QQ",
enumerable : true,
}
});
car.getModel();
// 如果不用上面那種,則
var vehiclePrototype = {
init : function (carModel) {
this.model = carModel;
},
getModel : function () {
console.log("the model of this vehicle is " + this.model);
}
};
function vehicle (model) {
function F () {};
F.prototype = vehiclePrototype;
var f = new F();
f.init(model);
return f;
};
yourCar = new vehicle("QQ");
yourCar.getModel();
/**
* 第三種方式
*/
var beget = (function () {
function F () {};
return function (proto) {
F.prototype = proto;
return new F();
};
})();
yourCar = new beget(vehiclePrototype);
yourCar.init("QQ");
yourCar.getModel();
實現結果:
優缺點
- 原型模式允許在執行時動態改變具體的實現型別;
- 改變值以指定新物件;
- 改變結構以指定新物件;
- 減少子類的構造;
注意的是
1. 每個類都必須配備一個克隆方法,比如當所考慮的類已經存在時就難以新增clone操作,當內部包括一些不支援拷貝或有迴圈引用的物件時,不不容易實現克隆;