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