<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        關于js設計模式的超詳細介紹

        來源:懂視網 責編:小采 時間:2020-11-27 19:55:25
        文檔

        關于js設計模式的超詳細介紹

        關于js設計模式的超詳細介紹:本篇文章給大家分享的內容是關于js設計模式的超詳細介紹,有著一定的參考價值,有需要的朋友可以參考一下js設計模式Jan 14, 2017 | 學習筆記 | 3387 Hits目錄前言單體模式工廠模式迭代器模式裝飾者模式策略模式外觀模式代理模式中介者模式觀察者模式前言本文
        推薦度:
        導讀關于js設計模式的超詳細介紹:本篇文章給大家分享的內容是關于js設計模式的超詳細介紹,有著一定的參考價值,有需要的朋友可以參考一下js設計模式Jan 14, 2017 | 學習筆記 | 3387 Hits目錄前言單體模式工廠模式迭代器模式裝飾者模式策略模式外觀模式代理模式中介者模式觀察者模式前言本文

        本篇文章給大家分享的內容是關于js設計模式的超詳細介紹,有著一定的參考價值,有需要的朋友可以參考一下

        js設計模式

        目錄

      1. 前言

      2. 單體模式

      3. 工廠模式

      4. 迭代器模式

      5. 裝飾者模式

      6. 策略模式

      7. 外觀模式

      8. 代理模式

      9. 中介者模式

      10. 觀察者模式

      11. 前言

        本文參考于《javascript模式》,因此會大量內容會和書中相同,手上有這本書的朋友可以直接看書。因為我的記憶習慣是抄書,所以我會先抄寫下來再發到博客上。

        單體模式

        單體模式思想在于保證一個特定類僅有一個實例,意味著當你第二次使用同一個類創建信對象時,應得到和第一次創建對象完全相同。

        方法一


        function Universe(){
        if(typeof Universe.instance==="object"){
        return Universe.instance; //防止被篡改
        }
        this.xx="xx";
        Universe.instance=this;
        return this;
        }
        var uni=new Universe();
        var uni2=new Universe();
        uni===uni2; //true

        缺點

        instance 屬性暴露。

        方法二

        使用閉包


        function Universe(){
        var instance=this; //緩存this
        this.xx="xx";
        Universe=function(){ //重寫此構造函數
        return instance;
        }
        }
        var uni=new Universe();
        var uni2=new Universe();
        uni===uni2; //true

        缺點

        因為重寫了構造函數,constructor 還是指向了老的構造函數,且實例化后在添加原型屬性也是不一樣的。如下


        var uni = new Universe();
        Universe.prototype.a = 1
        var uni2 = new Universe();
        console.log(uni === uni2) //true
        console.log(uni.a) //undefinded
        console.log(uni2.a) //undefinded
        console.log(uni.constructor === Universe); //false

        方法三

        解決方法二問題。


        function Universe(){
        var instance;
        Universe=function Universe(){
        return instance ;
        }
        Universe.prototype=this; //保存原型屬性
        instance=new Universe();
        instance.constructor=Universe;
        instance.xx="xx";
        }

        方法四

        自運行函數。


        var Universe;
        (function(){
        var instance;
        Universe=function Universe(){
        if(instance){
        return instance;
        }
        instance=this;
        this.xx="xx";
        }
        })();
        var uni = new Universe();
        Universe.prototype.a = 1
        var uni2 = new Universe();
        console.log(uni === uni2) //true
        console.log(uni.a) //1
        console.log(uni2.a) //1
        console.log(uni.constructor === Universe); //true

        工廠模式

        工廠模式是為了創建對象。

        例子

      12. 公共構造函數 CarMaker

      13. 名為factory的CarMaker靜態方法來創建car對象


      14. var corolla=CarMaker.factory('compact');
        var solstice=CarMaker.factory('convertible');
        var cherokee=CarMaker.factory('suv');
        corolla.drive() //I have 4 doors
        solstice.drive() //I have 2 doors
        cherokee.drive() //I have 6 doors

        實現



        function CarMaker() {}
        CarMaker.prototype.drive = function() {
        return "I have " + this.doors + " doors";
        }
        CarMaker.compact = function() {
        this.doors = 4;
        }
        CarMaker.convertible = function() {
        this.doors = 2
        }
        CarMaker.suv = function() {
        this.doors = 6;
        }
        CarMaker.factory = function(type) {
        if (typeof CarMaker[type] !== "function") {
        throw "Error"
        }
        if (typeof CarMaker[type].prototype.drive !== "function") {
        CarMaker[type].prototype = new CarMaker();
        }
        var newCar = new CarMaker[type]();
        return newCar;
        }
        var corolla = CarMaker.factory('compact');
        console.log(corolla.drive()); //I have 4 doors

        內置工廠對象

        Object() 構造函數即為內置工廠對象。

        迭代器模式

        有一個包含某種數據集合的對象,該數據可能存儲在一個復雜數據結構內部,而要提供一個簡單方法訥訥感訪問到數據結構中沒一個元素。

      15. next() 下一個

      16. hasNext() 是否有下一個

      17. reWind() 重置指針

      18. current() 返回當前


      19. var agg = (function() {
        var index = 0;
        var data = [1, 2, 3, 4, 5, 6];
        var length = data.length;
        return {
        next: function() { //這里是從第一個數據開始
        輸出 本例中為 1 if (!this.hasNext()) { return null; } var element = data[index]; index++; return element; }, hasNext: function() { return index < length; }, reWind: function() { index = 0; }, current: function() { return data[index]; } } })(); while (agg.hasNext()) { console.log(agg.next()); //1,2,3,4,5,6 } agg.reWind(); //此時重置指針到0

        裝飾者模式

        可以在運行時候添加附加功能到對象中,他的一個方便特征在于其預期行為的可定制和可配置特性。

        例子 假設在開發一個銷售商品的Web應用,每一筆信銷售都是一個人新的 sale 對象。該對象“知道”有關項目的價格,并可以通過 getPrice() 方法返回加個。
        根據不同情況,可以用額外的功能裝飾此對象。
        假設客戶在魁北克省,買房需要支付聯邦稅和魁北克省稅,則此時需要調用聯邦稅裝飾者和魁北克省稅裝飾者。


        var sale=new Sale(100);
        sale=sale.decorate("fedtax"); //聯邦稅
        sale=sale.decorate("quebec"); //魁北克省稅
        sale=sale.decorate("miney"); //轉為美元格式
        sale.getPrice(); //返回價格

        并且裝飾是可選的,例如不再魁北克省有可能沒有省稅。

        方法一


        function Sale(price) {
        this.price = price;
        }
        Sale.prototype.getPrice = function() {
        return this.price;
        };
        Sale.decorators = {}; //儲存裝飾者的對象
        //裝飾者
        Sale.decorators.fedtax = {
        getPrice: function() {
        var price = this.uber.getPrice();
        return price * 0.8; //對price進行處理
        },
        }
        Sale.decorators.quebec = {
        getPrice: function() {
        var price = this.uber.getPrice();
        return price * 0.7; //對price進行處理
        },
        }
        Sale.decorators.money = {
        getPrice: function() {
        var price = this.uber.getPrice();
        return "$" + price * 0.9; //對price進行處理
        },
        }
        /*decorate() 方法
        調用裝飾者方法 sale.=sale.decorate("fedtax");
        fedtax字符串對應 Sale.decorators中的對象屬性。新裝飾對象 newobj 將繼承目前我們所擁有的對象,這就是ixiangthis
        為了完成繼承部分代碼,此時需要一個臨時構造函數,先設置 newobj 的 uber 屬性,以便于自對象可以訪問到父對象。之后從裝飾者中
        將所有的額外屬性復制到新裝飾的對象 newobj 中,最后返回 newobj。
        */
        Sale.prototype.decorate = function(decorate) {
        var F = function() {};
        var overrides = this.constructor.decorators[decorate]; //獲取裝飾者對象
        F.prototype = this;
        var newobj = new F();
        newobj.uber = F.prototype;
        for (var key in overrides) {
        if (overrides.hasOwnProperty) { //判斷對象是不是自身的
        newobj[key] = overrides[key];
        }
        }
        return newobj;
        };
        var sale = new Sale(100);
        sale = sale.decorate("fedtax"); //聯邦稅
        sale = sale.decorate("quebec"); //魁北克省稅
        sale = sale.decorate("money"); //轉為美元格式
        console.log(sale.getPrice()); //$50.4

        方法二

        此方法使用列表實現,而且相對來說比較好理解一點。本質就是把裝飾者名稱保存到一個列表中并且一次調用此列表中的方法。


        function Sale(price) {
        this.price = price;
        this.decorateList = [];
        }
        Sale.decorators = {};
        Sale.decorators.fedtax = {
        getPrice: function(price) {
        var price = this.uber.getPrice();
        return price * 0.8; //對price進行處理
        },
        }
        Sale.decorators.quebec = {
        getPrice: function(price) {
        var price = this.uber.getPrice();
        return price * 0.7; //對price進行處理
        },
        }
        Sale.decorators.money = {
        getPrice: function(price) {
        var price = this.uber.getPrice();
        return "$" + price * 0.9; //對price進行處理
        },
        }
        Sale.prototype.decorate = function(decorator) {
        this.decorateList.push(decorator);
        };
        Sale.prototype.getPrice = function() {
        var price = this.price;
        this.decorateList.forEach(function(name) {
        price = Sale.decorators[name].getPrice(price);
        });
        return price;
        };
        var sale = new Sale(100);
        sale = sale.decorate("fedtax"); //聯邦稅
        sale = sale.decorate("quebec"); //魁北克省稅
        sale = sale.decorate("money"); //轉為美元格式
        console.log(sale.getPrice()); //$50.4

        策略模式

        策略模式支持在運行時候選擇算法。例如用在表單驗證問題上,可以創建一個具有 validate() 方法的驗證器對象,無論表單具體類型是什么,該方法都會被調用,
        并且返回結果或者錯誤信息。


        var validator = {
        // 所有可以的驗證規則處理類存放的地方,后面會單獨定義
        types: {},
        // 驗證類型所對應的錯誤消息
        messages: [],
        // 當然需要使用的驗證類型
        config: {},
        // 暴露的公開驗證方法
        // 傳入的參數是 key => value對
        validate: function (data) {
        var i, msg, type, checker, result_ok;
        // 清空所有的錯誤信息
        this.messages = [];
        for (i in data) {
        if (data.hasOwnProperty(i)) {
        type = this.config[i]; // 根據key查詢是否有存在的驗證規則
        checker = this.types[type]; // 獲取驗證規則的驗證類
        if (!type) {
        continue; // 如果驗證規則不存在,則不處理
        }
        if (!checker) { // 如果驗證規則類不存在,拋出異常
        throw {
        name: "ValidationError",
        message: "No handler to validate type " + type
        };
        }
        result_ok = checker.validate(data[i]); // 使用查到到的單個驗證類進行驗證
        if (!result_ok) {
        msg = "Invalid value for *" + i + "*, " + checker.instructions;
        this.messages.push(msg);
        }
        }
        }
        return this.hasErrors();
        },
        // helper
        hasErrors: function () {
        return this.messages.length !== 0;
        }
        };
        //然后剩下的工作,就是定義types里存放的各種驗證類了
        // 驗證給定的值是否不為空
        validator.types.isNonEmpty = {
        validate: function (value) {
        return value !== "";
        },
        instructions: "傳入的值不能為空"
        };
        // 驗證給定的值是否是數字
        validator.types.isNumber = {
        validate: function (value) {
        return !isNaN(value);
        },
        instructions: "傳入的值只能是合法的數字,例如:1, 3.14 or 2010"
        };
        // 驗證給定的值是否只是字母或數字
        validator.types.isAlphaNum = {
        validate: function (value) {
        return !/[^a-z0-9]/i.test(value);
        },
        instructions: "傳入的值只能保護字母和數字,不能包含特殊字符"
        };
        //使用的時候,我們首先要定義需要驗證的數據集合,然后還需要定義每種數據需要驗證的規則類型,代碼如下:
        var data = {
        first_name: "Tom",
        last_name: "Xu",
        age: "unknown",
        username: "TomXu"
        };
        validator.config = {
        first_name: 'isNonEmpty',
        age: 'isNumber',
        username: 'isAlphaNum'
        };
        //最后獲取驗證結果 
        validator.validate(data);
        if (validator.hasErrors()) {
        console.log(validator.messages.join("\n"));
        }

        策略模式定義及例子實現參考與《javascript模式》及 湯姆大叔的博客

        外觀模式

        外觀模式即讓多個方法一起被調用

        例如。 stopPropagation() 和 preventDefault() 兼容性一起調用。


        var myEvent = {
        stop: function(e) {
        if (typeof e.preventDefault() === "function") {
        e.preventDefault();
        }
        if (typeof e.stopPropagation() === "function") {
        e.stopPropagation();
        }
        //for IE
        if (typeof e.returnValue === "boolean") {
        e.returnValue = false;
        }
        if (typeof e.cancelBubble === "boolean") {
        e.cancelBubble = true;
        }
        }
        }

        代理模式

        在代理模式中,一個對象充當另外一個對象的接口,和外觀模式區別是:外觀模式是合并調用多個方法。
        代理模式是介于對象的客戶端和對象本身之間,并且對該對象的訪問進行保護。

        包裹例子

        現在有個包裹,賣家要把這個包裹寄給gary,則需要通過快遞公司寄過來,此時快遞公司就是一個 proxy


        var package = function(receiver) {
        this.receiver = receiver;
        }
        var seller = function(package) {
        this.package = package;
        this.send = function(gift) {
        return package.receiver + "你的包裹:" + gift;
        }
        }
        var express = function(package) {
        this.package = package;
        this.send = function(packageName) {
        return new seller(package).send(packageName);
        }
        }
        //調用
        var ems = new express(new package("gary"));
        console.log(ems.send("鍵盤")); //gary你的包裹:鍵盤

        論壇權限管理例子

        本例子參考與 大熊君

      20. 權限列表

      21. 發帖 1

      22. 帖子審核 2

      23. 刪帖 3

      24. 留言、回復 4

      25. 用戶代碼權限
        注冊用戶0011 4
        論壇管理員0022 3 4
        系統管理員0031 2 3 4
        游客000null

        用戶類


        function User(name, code) {
        this.name = name;
        this.code = code;
        }
        User.prototype.getName = function() {
        return this.name;
        };
        User.prototype.getCode = function() {
        return this.code;
        };
        User.prototype.post = function() {
        //發帖功能
        };
        User.prototype.remove = function() {
        // 刪帖功能
        };
        User.prototype.check = function() {
        //審核
        };
        User.prototype.comment = function() {
        //留言回復
        };

        論壇類


        function Forum(user) {
        this.user=user;
        }
        Forum.prototype.getUser = function () {
        return this.user;
        };
        Forum.prototype.post = function () {
        var code=this.user.getCode();
        if(code=="001"||code=="003"){
        return this.user.post();
        }else{
        return false;
        }
        };
        Forum.prototype.remove = function () {
        var code=this.user.getCode();
        if(code=="002"||code=="003"){
        return this.user.remove();
        }else{
        return false;
        }
        };
        Forum.prototype.check = function () {
        var code=this.user.getCode();
        if(code=="002"||code=="003"){
        return this.user.check();
        }else{
        return false;
        }
        };
        Forum.prototype.comment = function () {
        var code=this.user.getCode();
        if(code=="001"||code=="002"||code=="003"){
        return this.user.comment();
        }else{
        return false;
        }
        };

        運行


        new Forum(new User("administartor","003"));

        中介者模式

        中介者模式可以讓多個對象之間松耦合,并降低維護成本

        例如:游戲程序,兩名玩家分別給與半分鐘時間來競爭決出勝負(誰按鍵的次數多勝出,這里玩家1按1,玩家2按0)

      26. 計分板(scoreboard)

      27. 中介者 (mediator)

      28. 中介者知道所有其他對象的信息。他與輸入設備(此時是鍵盤)進行通信并處理鍵盤上的按鍵時間,之后還將消息通知玩家。玩家玩游戲同時(每一分都更新自己分數)還要
        通知中介者他所做的事情。中介者將更新后的分數傳達給計分板。

        除了中介者莫有對象知道其他對象。

        圖示

        圖示


        function Player(name) {
        this.points = 0;
        this.name = name;
        }
        Player.prototype.play = function() {
        this.points += 1;
        mediator.played();
        };
        var scoreboard = {
        element: "這里是獲取的element用于展示分數",
        update: function(score) { //更新分數
        var msg;
        for (var key in score) {
        if (score.hasOwnProperty(key)) {
        msg += score[key];
        }
        }
        this.element.innerText = msg;
        },
        }
        var mediator = {
        players: {}, //玩家對象
        setup: function() {
        var players = this.players;
        players.home = new Player("home");
        players.guest = new Player('guest');
        },
        played: function() {
        var players = this.players;
        var score = {
        home: players.home.points,
        guest: players.guest.points
        }
        },
        keypress: function(e) {
        e = e || window.event;
        if (e.which === 49) { //or keycode 對應按鍵 1
        mediator.players.home.play();
        return;
        }
        if (e.which === 48) { // 對應按鍵 0
        mediator.player.guest.play();
        return;
        }
        },
        }
        //運行
        mediator.setup();
        window.onkeypress = mediator.keypress;
        setTimeout(function() { //設置30秒游戲時間
        window.onkeypress = null;
        alert("game end");
        }, 30000);

        觀察者模式

        觀察者模式在 javascript 中使用非常廣泛。所有的瀏覽器時間就是該模式的實現,node.js中的events也是此模式實現。
        此模式另一個名稱是 訂閱/發布模式
        設計這種模式原因是促進形成松散耦合,在這種模式中,并不是一個對象調用另一個對象的方法,而是一個對象訂閱另一個對象的
        特定活動并在狀態改編后獲得通知。訂閱者因此也成為觀察者,而被觀察的對象成為發布者或者主題。當發生了一個重要事件時候
        發布者會通知(調用)所有訂閱者并且可能經常已事件對象的形式傳遞消息。

        小結

        1.單體模式

        針對一個類僅創建一個對象。

        2.工廠模式

        根據字符串制定類型在運行時創建對象的方法。

        3.迭代器模式

        提供一個API來遍歷或者操作復雜的自定義數據結構。

        4.裝飾者模式

        通過從預定義裝飾者對象中添加功能,從而在運行時侯調整對象

        5.策略模式

        在懸在最佳策略以處理特定任務的時候仍然保持相同的接口。

        6.外觀模式

        通過把常用方法包裝到一個新方法中,從來提供一個更為便利的API。

        7.代理模式

        通過包裝一個對象從而控制對它的訪問,其中主要方法是將方位聚集為租或者
        僅當真正必要時侯才執行訪問,從未避免高昂的操作開銷。

        8.終結者模式

        通過是你的對象之間相互不直接“通話”,而是通過一個中介者對子昂進行通信,
        從而形成松散耦合。

        9.觀察者模式

        通過創建“可觀察”的對象,當發生一個感興趣的事件時可將改時間通告給所有觀察者
        從而形成松散耦合。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        關于js設計模式的超詳細介紹

        關于js設計模式的超詳細介紹:本篇文章給大家分享的內容是關于js設計模式的超詳細介紹,有著一定的參考價值,有需要的朋友可以參考一下js設計模式Jan 14, 2017 | 學習筆記 | 3387 Hits目錄前言單體模式工廠模式迭代器模式裝飾者模式策略模式外觀模式代理模式中介者模式觀察者模式前言本文
        推薦度:
        標簽: 模式 介紹 js
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲一区二区三区影院| 亚洲Av无码乱码在线观看性色 | 超清首页国产亚洲丝袜| 久久亚洲精品高潮综合色a片| 夫妻免费无码V看片| 亚洲精品蜜夜内射| 手机看片久久国产免费| 狼色精品人妻在线视频免费| 免费一区二区视频| 亚洲免费在线观看| 日本亚洲成高清一区二区三区| 免费无码H肉动漫在线观看麻豆| 国产亚洲综合色就色| 9420免费高清在线视频| 亚洲日韩中文字幕天堂不卡| 97碰公开在线观看免费视频| 午夜亚洲国产理论片二级港台二级| 成人国产mv免费视频| 一级一级一级毛片免费毛片| 亚洲乱码一区二区三区在线观看| 久久九九AV免费精品| 亚洲免费福利视频| 国产乱子影视频上线免费观看| 免费看一级一级人妻片| 国产AV无码专区亚洲AV毛网站| 18禁男女爽爽爽午夜网站免费| 亚洲高清一区二区三区| gogo全球高清大胆亚洲| 国内精品免费在线观看| 亚洲中文字幕一二三四区苍井空| 国产成人免费全部网站| 在线观看免费无码专区| 亚洲一久久久久久久久| 亚洲一级特黄大片在线观看| 8x8x华人永久免费视频| 亚洲性无码一区二区三区| 亚洲午夜精品第一区二区8050| 免费国产黄网站在线观看视频 | 人成电影网在线观看免费| 亚洲成人中文字幕| 日本不卡高清中文字幕免费|