原型模式(Prototype Pattern)是一種創(chuàng)造型設(shè)計模式,其核心思想在于通過復(fù)制“原型”來創(chuàng)建對象,而非直接實例化。在原型模式中,我們首先創(chuàng)造一個原型對象,接著通過對其進(jìn)行復(fù)制,獲得新的實例。這些原型對象儲存在一個共享的“原型管理器”中,當(dāng)需要新的對象時,只需從管理器獲取原型的復(fù)制。
讓我們以一個具體場景為例,考慮開發(fā)一個鴨子養(yǎng)殖游戲。游戲中需要生成兩種鴨子:北京鴨和綠頭鴨。這兩種鴨子共享一些屬性和方法,如叫聲、游泳和渲染模型,但叫聲和渲染模型是不同的。
如果每次都從頭創(chuàng)建鴨子對象,將會產(chǎn)生大量冗余代碼,如下所示:
const duck1 = { name: '鴨子1', quack() {}, swim() {}, render() {}};const duck2 = { name: '鴨子2', quack() {}, swim() {}, render() {}};
這種方式重復(fù)定義相同的 quack 和 swim 方法,效率低下。如果使用簡單工廠模式,代碼如下:
function createDuck(type) { let duck; if (type === 'beijing') { duck = new BeijingDuck(); } else if (type === 'greenheaded') { duck = new GreenHeadedDuck(); } duck.swim = function() { console.log('swimming...'); } duck.render = function() { console.log('render duck model...') } return duck; }const beijingDuck = createDuck('beijing'); const greenDuck = createDuck('greenheaded');
但是,這樣每次創(chuàng)建鴨子對象都需要重新定義 swim 和 render 方法,不夠高效。
更優(yōu)雅的方式是將共有部分提取為一個原型:
// 鴨子原型const DuckPrototype = { swim() {}, render() {} };// 創(chuàng)建具體鴨子時復(fù)制原型function createBeijingDuck() { const duck = Object.create(DuckPrototype); duck.quack = function() {} return duck;}function createGreenDuck() { const duck = Object.create(DuckPrototype); duck.quack = function() {} return duck; }
以上代碼展示了如何在鴨子游戲中應(yīng)用原型模式。通過原型模式,我們只需定義一次共有屬性和方法,然后通過復(fù)制原型來實例化新對象。這避免了重復(fù)代碼,提高了對象創(chuàng)建效率,并建立了對象之間的關(guān)系,方便基于原型進(jìn)行擴(kuò)展。
原型模式與相關(guān)模式的區(qū)別:
那么,如何使用 TypeScript 實現(xiàn)更優(yōu)雅的原型模式呢?
// 原型接口interface Prototype { clone(): Prototype; }// 原型管理器類class PrototypeManager { private prototypes: {[key: string]: Prototype} = {}; // 省略方法定義}// 具體原型類class ConcretePrototype implements Prototype { clone() { return Object.create(this); }}// 使用// 初始化原型管理器const manager = new PrototypeManager();// 設(shè)置原型對象manager.set('proto', new ConcretePrototype()); // 請求原型復(fù)制實例化const prototypeInstance = manager.get('proto').clone();
以上代碼定義了原型接口、原型管理器類和具體原型類,還提供了簡單的使用示例。從示例中可以看出,原型模式的關(guān)鍵是通過原型管理器來復(fù)制原型對象從而創(chuàng)建實例。
原型模式的主要優(yōu)點(diǎn)包括:
原型模式的缺點(diǎn)包括:
原型模式在以下場景中常見應(yīng)用:
以下是一些建議,在前端開發(fā)中更適合使用原型模式的情況:
1)創(chuàng)建組件類的原型:通過創(chuàng)建組件類的原型對象,使用 Object.create() 方法基于該原型快速創(chuàng)建組件實例,從而避免重復(fù)編寫組件邏輯。
// 原型類const ComponentPrototype = { // 組件邏輯 render() { // ... }};// 基于原型創(chuàng)建實例 const ComponentInstance = Object.create(ComponentPrototype);
2)復(fù)用和配置原型對象:設(shè)計一些可配置的原型對象,如 API 配置對象,然后復(fù)制和配置這些原型來生成不同的實例,避免重復(fù)創(chuàng)建。
// 可配置的原型const APIConfigPrototype = { baseURL: 'https://example.com', timeout: 1000,};// 復(fù)制原型并配置生成實例const config = Object.assign({}, APIConfigPrototype, { timeout: 3000 });
3)代理原型對象:通過原型對象實現(xiàn)代理,避免每次訪問都重新創(chuàng)建目標(biāo)對象。
// 原型作為代理對象const proxyPrototype = { target: null, get(key) { // 懶加載 if (!this.target) { this.target = createTargetObject(); } return this.target[key]; }}// 使用代理原型 const proxy = Object.create(proxyPrototype);proxy.foo // 觸發(fā)代理邏輯
原型模式和 JavaScript 中的原型繼承(prototype)存在以下主要區(qū)別:
綜上所述,原型模式是一種更抽象和全面的對象復(fù)用方式,而 JavaScript 中的原型繼承只是一種具體的繼承實現(xiàn)方式,它們在核心思想上有所不同。然而,它們在提高實例化效率方面具有一定的相似性。
原型模式是一種創(chuàng)造型設(shè)計模式,通過復(fù)制現(xiàn)有對象的原型來創(chuàng)建新對象,提高對象創(chuàng)建效率和復(fù)用性。核心思想是在一個原型對象的基礎(chǔ)上,通過復(fù)制來生成新實例,避免重復(fù)初始化。
在實際開發(fā)中,原型模式優(yōu)化對象創(chuàng)建,通過共享原型對象避免重復(fù)定義屬性和方法,提高代碼效率。例如,前端可用于創(chuàng)建組件實例,避免重復(fù)編寫組件邏輯。
實現(xiàn)原型模式包括創(chuàng)建原型對象,然后通過復(fù)制原型創(chuàng)建新實例。原型對象通常存儲于原型管理器中,供需要創(chuàng)建對象時復(fù)制使用。
與JavaScript的原型繼承不同,原型模式更抽象靈活。它動態(tài)添加刪除原型,避免構(gòu)造函數(shù)污染,隱藏實例化復(fù)雜性。注意每具體原型需實現(xiàn)接口,增加開發(fā)成本。
總之,原型模式通過復(fù)制對象的原型創(chuàng)建新對象,提高對象創(chuàng)建效率和復(fù)用性。頻繁創(chuàng)建相似對象場景下,原型模式是有用設(shè)計模式。
本文鏈接:http://www.tebozhan.com/showinfo-26-5142-0.html三言兩語說透設(shè)計模式的藝術(shù)-原型模式
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: Rust“巨坑”?真相來了!