工廠模式在JS中的實踐

 本文版權歸博客園和做者吳雙本人共同全部,轉載和爬蟲必須註明原文地址 www.cnblogs.com/tdwscss

一.   寫在前面

   工廠模式和抽象工廠在後臺代碼中的使用,相信你必定很是熟悉,因此關於概念的東西也用不着我多說。你能夠用其作爲類與類之間,層與層之間的解耦。工廠模式沒有什麼難點,在JS中其實思想也是同樣的,因此廢話很少說,直接上實踐的場景和代碼。html

 二.  場景描述

   1.最近的項目的登錄使用了Owin認證,因此token必須找好地方進行存儲,鑑於token須要在請求API資源的時候放到請求頭的Authorization當中,以便在進入WebAPI前進行身份驗證。因此我不想在主流瀏覽器中的cookie中存儲token,由於這樣一來,每次Cookie中帶一份token,Authorization中又帶一份token.多傳輸一次不說,還讓人感到很low.這麼 這麼low的行爲,你忍心使用嗎。因此我但願把token存儲於localStorage當中。那麼問題來了,不支持H5的瀏覽器怎麼辦?前端

   2.爲了未來把全部前端資源置於CDN, 前端僅擁有html,css和js。頁面加載到瀏覽器客戶端後,全部動態資源走AJAX,而且全部資源均跨域。那麼問題又來了,跨域很容易解決,在IE8,IE9這種默認關閉跨域功能的瀏覽器怎麼辦?git

 三. 公共JS結構一覽

我一般會給應用定義一個全局Application.js。其中大概包括以下內容。 先上總體代碼結構,供參考github

 四. 引入工廠思想解決問題

 爲了解決上述兩個問題,因此引入工廠模式,在工廠中建立對象,工廠中根據不一樣瀏覽器類型,建立不一樣對象。ajax

也就是說在解決問題一上,在瀏覽器支持H5的時候,存儲token於localStorage。在不支持h5的瀏覽器中仍是存於cookie.編程

因此產生了兩個JS對象,CookieStorageUtil對象,LocalStorageUtil對象。而且他們應該實現相同的「接口」,在這裏我沒有使用JS代碼來模仿接口,而是採用註釋的形式,標註兩個對象須要實現相同的接口,實現接口中的兩個方法write()和get()。並規範代碼,下劃線開頭的爲私有方法,這樣一來從此修改內部代碼的時候,私有方法隨便改,對外部暴露的方法名稱不變就好,是否是有點像後臺的面向接口編程呢?其實JS也是同樣的。再多費一句話,若是我不使用JS的function模擬類的話,是沒法達到真正的方法私有,因此若是有人調用下劃線'_'開頭的私有方法,在從此私有方法有變更的時候影響了功能,那就不是個人鍋咯?設計模式

仍是上代碼靠譜:跨域

 1     /**
 2      * Storage Factory  -Author 吳雙   cnblogs.com/tdws
 3      */
 4     StorageUtilManager: new Object({
 5         createStorageUtil: function () {
 6             if (window.applicationCache) {
 7                 return AppUtil.LocalStorageUtil;
 8             } else {
 9                 return AppUtil.CookieStorageUtil;
10             }
11         }
12     }),
13     /**
14      * implement Storage  -Author 吳雙
15      * write()
16      * get()
17      */
18     CookieStorageUtil: {
19         write: function (key, dataObj) {
20             this._clearCookie(key);
21             //寫入的字符串
22             var dataObjStr = JSON.stringify(dataObj);
23             this._setCookie(key, dataObjStr, 15);
24         },
25         get: function (key) {
26             return this._getCookie(key);
27         },
28         _setCookie: function (cname, cvalue, exdays) {
29             var d = new Date();
30             d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
31             var expires = "expires=" + d.toUTCString();
32             var path = "path=/";
33             document.cookie = cname + "=" + cvalue + "; " + expires + "; " + path;
34         },
35         _getCookie: function (cname) {
36             var name = cname + "=";
37             var ca = document.cookie.split(';');
38             for (var i = 0; i < ca.length; i++) {
39                 var c = ca[i];
40                 while (c.charAt(0) == ' ') c = c.substring(1);
41                 if (c.indexOf(name) != -1) return c.substring(name.length, c.length);
42             }
43             return null;
44         },
45         _clearCookie: function (key) {
46             this._setCookie(key, "", -1);
47         }
48     },
49     /**
50      * implement Storage   cnblogs.com/tdws
51      * write()
52      * get()
53      */
54     LocalStorageUtil: {
55         write: function (key, dataObj) {
56             this._writeLocalStorage(key, dataObj);
57         },
58         get: function (key) {
59             return this._getFromLocalStorage(key);
60         },
61         _writeLocalStorage: function (key, dataObj) {
62             var localStorage = window.localStorage;
63             localStorage.removeItem(key);
64             //對象轉化爲字符串,將objStr按正常的方式存入localStorage中
65             var dataObjStr = JSON.stringify(dataObj);
66             localStorage.setItem(key, dataObjStr);
67         },
68         _getFromLocalStorage: function (key) {
69             var localStorage = window.localStorage;
70             return localStorage.getItem(key);
71         },
72         _removeLocalStorage: function (key) {
73             var localStorage = window.localStorage;
74             localStorage.removeItem(key);
75         }
76     }

這樣第二個問題也獲得瞭解決,在不支持跨域的瀏覽器建立XDomainRequest對象來作請求,兩個HttpUtil對象依然實現相同的接口中的方法。在這個跨域問題上,推薦使用gayhub中的一個1.8k的JS https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest瀏覽器

對了,爲了不使用工廠模式,使代碼調用複雜,咱們能夠簡化JS

AppUtil.currentHttpUtil = AppUtil.HttpUtilManager.createHttpUtil();

 五. 寫在最後

 因此有了這樣的方式,問題平滑的解決了,兩個StorageUtil與調用方,經過工廠StorageUtilManager完成解耦。可能你看完代碼後說,不就是多了一個Manager嗎?這也很簡單啊,是啊,就是這麼簡單,這就是設計模式,它僅僅是前人的經驗模式,它更平滑的解決咱們的實際問題。

  若是個人點滴分享對你有點滴幫助,歡迎點擊下方紅色按鈕關注,我將持續輸出分享。也歡迎爲你本身也爲我點贊支持。

                                                   —— 保持學習,謹記謙虛。不端不裝,有趣有夢。

相關文章
相關標籤/搜索