自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

十種 JavaScript 設(shè)計(jì)模式

開發(fā) 前端
設(shè)計(jì)模式是針對(duì)常見軟件問題的高級(jí)面向?qū)ο蠼鉀Q方案。模式是關(guān)于對(duì)象的可重用設(shè)計(jì)和交互。在討論復(fù)雜的設(shè)計(jì)解決方案時(shí),每個(gè)模式都有一個(gè)名稱并成為詞匯表的一部分。

介紹

設(shè)計(jì)模式是針對(duì)常見軟件問題的高級(jí)面向?qū)ο蠼鉀Q方案。模式是關(guān)于對(duì)象的可重用設(shè)計(jì)和交互。在討論復(fù)雜的設(shè)計(jì)解決方案時(shí),每個(gè)模式都有一個(gè)名稱并成為詞匯表的一部分。

在本教程中,我為每個(gè) GoF 模式提供了 JavaScript 示例。大多數(shù)情況下,它們遵循原始圖案設(shè)計(jì)的結(jié)構(gòu)和意圖。這些示例演示了每種模式背后的原則,但并未針對(duì) JavaScript 進(jìn)行優(yōu)化。

01.Abstract Factory 

Abstract Factory創(chuàng)建由共同主題相關(guān)的對(duì)象。在面向?qū)ο缶幊讨?,工廠是創(chuàng)建其他對(duì)象的對(duì)象。抽象工廠抽象出新創(chuàng)建的對(duì)象共享的主題。

圖片

function Employee(name) {
    this.name = name;


    this.say = function () {
        console.log("I am employee " + name);
    };
}


function EmployeeFactory() {


    this.create = function (name) {
        return new Employee(name);
    };
}


function Vendor(name) {
    this.name = name;


    this.say = function () {
        console.log("I am vendor " + name);
    };
}


function VendorFactory() {


    this.create = function (name) {
        return new Vendor(name);
    };
}


function run() {
    var persons = [];
    var employeeFactory = new EmployeeFactory();
    var vendorFactory = new VendorFactory();


    persons.push(employeeFactory.create("Joan DiSilva"));
    persons.push(employeeFactory.create("Tim O'Neill"));
    persons.push(vendorFactory.create("Gerald Watson"));
    persons.push(vendorFactory.create("Nicole McNight"));


    for (var i = 0, len = persons.length; i < len; i++) {
        persons[i].say();
    }
}

02.Builder 

Builder 模式允許客戶端僅通過指定類型和內(nèi)容來構(gòu)建復(fù)雜對(duì)象,細(xì)節(jié)完全對(duì)客戶隱藏。

圖片

function Shop() {
    this.construct = function (builder) {
        builder.step1();
        builder.step2();
        return builder.get();
    }
}


function CarBuilder() {
    this.car = null;


    this.step1 = function () {
        this.car = new Car();
    };


    this.step2 = function () {
        this.car.addParts();
    };


    this.get = function () {
        return this.car;
    };
}


function TruckBuilder() {
    this.truck = null;


    this.step1 = function () {
        this.truck = new Truck();
    };


    this.step2 = function () {
        this.truck.addParts();
    };


    this.get = function () {
        return this.truck;
    };
}


function Car() {
    this.doors = 0;


    this.addParts = function () {
        this.doors = 4;
    };


    this.say = function () {
        console.log("I am a " + this.doors + "-door car");
    };
}


function Truck() {
    this.doors = 0;


    this.addParts = function () {
        this.doors = 2;
    };


    this.say = function () {
        console.log("I am a " + this.doors + "-door truck");
    };
}


function run() {
    var shop = new Shop();
    var carBuilder = new CarBuilder();
    var truckBuilder = new TruckBuilder();
    var car = shop.construct(carBuilder);
    var truck = shop.construct(truckBuilder);


    car.say();
    truck.say();
}

03、Factory Method 

Factory Method 按照客戶的指示創(chuàng)建新對(duì)象。在 JavaScript 中創(chuàng)建對(duì)象的一種方法是使用 new 運(yùn)算符調(diào)用構(gòu)造函數(shù)。 

然而,在某些情況下,客戶端不知道或不應(yīng)知道要實(shí)例化多個(gè)候選對(duì)象中的哪一個(gè)。 

Factory Method 允許客戶端委托對(duì)象創(chuàng)建,同時(shí)仍然保留對(duì)要實(shí)例化的類型的控制。

圖片

var Factory = function () {
    this.createEmployee = function (type) {
        var employee;


        if (type === "fulltime") {
            employee = new FullTime();
        } else if (type === "parttime") {
            employee = new PartTime();
        } else if (type === "temporary") {
            employee = new Temporary();
        } else if (type === "contractor") {
            employee = new Contractor();
        }


        employee.type = type;


        employee.say = function () {
            console.log(this.type + ": rate " + this.hourly + "/hour");
        }


        return employee;
    }
}


var FullTime = function () {
    this.hourly = "$12";
};


var PartTime = function () {
    this.hourly = "$11";
};


var Temporary = function () {
    this.hourly = "$10";
};


var Contractor = function () {
    this.hourly = "$15";
};


function run() {


    var employees = [];
    var factory = new Factory();


    employees.push(factory.createEmployee("fulltime"));
    employees.push(factory.createEmployee("parttime"));
    employees.push(factory.createEmployee("temporary"));
    employees.push(factory.createEmployee("contractor"));


    for (var i = 0, len = employees.length; i < len; i++) {
        employees[i].say();
    }
}

04、Adapter

Adapter模式將一個(gè)接口(對(duì)象的屬性和方法)轉(zhuǎn)換為另一個(gè)接口。Adapter允許編程組件協(xié)同工作,否則由于接口不匹配而無法協(xié)同工作。適配器(Adapter)模式也稱為包裝器模式。

圖片

// old interface


function Shipping() {
    this.request = function (zipStart, zipEnd, weight) {
        // ...
        return "$49.75";
    }
}


// new interface


function AdvancedShipping() {
    this.login = function (credentials) { /* ... */ };
    this.setStart = function (start) { /* ... */ };
    this.setDestination = function (destination) { /* ... */ };
    this.calculate = function (weight) { return "$39.50"; };
}


// adapter interface


function ShippingAdapter(credentials) {
    var shipping = new AdvancedShipping();


    shipping.login(credentials);


    return {
        request: function (zipStart, zipEnd, weight) {
            shipping.setStart(zipStart);
            shipping.setDestination(zipEnd);
            return shipping.calculate(weight);
        }
    };
}


function run() {


    var shipping = new Shipping();
    var credentials = { token: "30a8-6ee1" };
    var adapter = new ShippingAdapter(credentials);


    // original shipping object and interface


    var cost = shipping.request("78701", "10010", "2 lbs");
    console.log("Old cost: " + cost);


    // new shipping object with adapted interface


    cost = adapter.request("78701", "10010", "2 lbs");


    console.log("New cost: " + cost);
}

05、Decorator

Decorator模式動(dòng)態(tài)地?cái)U(kuò)展(裝飾)對(duì)象的行為。在運(yùn)行時(shí)添加新行為的能力是由 Decorator 對(duì)象實(shí)現(xiàn)的,它“將自身包裝”在原始對(duì)象周圍。多個(gè)裝飾器可以向原始對(duì)象添加或覆蓋功能。

圖片

var User = function (name) {
    this.name = name;


    this.say = function () {
        console.log("User: " + this.name);
    };
}


var DecoratedUser = function (user, street, city) {
    this.user = user;
    this.name = user.name;  // ensures interface stays the same
    this.street = street;
    this.city = city;


    this.say = function () {
        console.log("Decorated User: " + this.name + ", " +
            this.street + ", " + this.city);
    };
}


function run() {


    var user = new User("Kelly");
    user.say();


    var decorated = new DecoratedUser(user, "Broadway", "New York");
    decorated.say();
}

06、Facade

Facade 模式提供了一個(gè)接口,使客戶免受一個(gè)或多個(gè)子系統(tǒng)中復(fù)雜功能的影響。這是一個(gè)看似微不足道但功能強(qiáng)大且極其有用的簡(jiǎn)單模式。它通常出現(xiàn)在圍繞多層架構(gòu)構(gòu)建的系統(tǒng)中。

圖片

var Mortgage = function (name) {
    this.name = name;
}


Mortgage.prototype = {


    applyFor: function (amount) {
        // access multiple subsystems...
        var result = "approved";
        if (!new Bank().verify(this.name, amount)) {
            result = "denied";
        } else if (!new Credit().get(this.name)) {
            result = "denied";
        } else if (!new Background().check(this.name)) {
            result = "denied";
        }
        return this.name + " has been " + result +
            " for a " + amount + " mortgage";
    }
}


var Bank = function () {
    this.verify = function (name, amount) {
        // complex logic ...
        return true;
    }
}


var Credit = function () {
    this.get = function (name) {
        // complex logic ...
        return true;
    }
}


var Background = function () {
    this.check = function (name) {
        // complex logic ...
        return true;
    }
}


function run() {
    var mortgage = new Mortgage("Joan Templeton");
    var result = mortgage.applyFor("$100,000");


    console.log(result);
}

07、Proxy

代理模式為另一個(gè)對(duì)象提供代理或占位符對(duì)象,并控制對(duì)另一個(gè)對(duì)象的訪問。

圖片

function GeoCoder() {


    this.getLatLng = function (address) {


        if (address === "Amsterdam") {
            return "52.3700° N, 4.8900° E";
        } else if (address === "London") {
            return "51.5171° N, 0.1062° W";
        } else if (address === "Paris") {
            return "48.8742° N, 2.3470° E";
        } else if (address === "Berlin") {
            return "52.5233° N, 13.4127° E";
        } else {
            return "";
        }
    };
}


function GeoProxy() {
    var geocoder = new GeoCoder();
    var geocache = {};


    return {
        getLatLng: function (address) {
            if (!geocache[address]) {
                geocache[address] = geocoder.getLatLng(address);
            }
            console.log(address + ": " + geocache[address]);
            return geocache[address];
        },
        getCount: function () {
            var count = 0;
            for (var code in geocache) { count++; }
            return count;
        }
    };
};


function run() {


    var geo = new GeoProxy();


    // geolocation requests


    geo.getLatLng("Paris");
    geo.getLatLng("London");
    geo.getLatLng("London");
    geo.getLatLng("London");
    geo.getLatLng("London");
    geo.getLatLng("Amsterdam");
    geo.getLatLng("Amsterdam");
    geo.getLatLng("Amsterdam");
    geo.getLatLng("Amsterdam");
    geo.getLatLng("London");
    geo.getLatLng("London");


    console.log("\nCache size: " + geo.getCount());


}

08、Mediator

Mediator模式通過封裝這些對(duì)象的交互方式來提供對(duì)一組對(duì)象的集中管理權(quán)。此模型對(duì)于需要管理復(fù)雜條件的場(chǎng)景很有用,在這種情況下,每個(gè)對(duì)象都知道組中任何其他對(duì)象的任何狀態(tài)更改。

圖片

var Participant = function (name) {
    this.name = name;
    this.chatroom = null;
};


Participant.prototype = {
    send: function (message, to) {
        this.chatroom.send(message, this, to);
    },
    receive: function (message, from) {
        console.log(from.name + " to " + this.name + ": " + message);
    }
};


var Chatroom = function () {
    var participants = {};


    return {


        register: function (participant) {
            participants[participant.name] = participant;
            participant.chatroom = this;
        },


        send: function (message, from, to) {
            if (to) {                      // single message
                to.receive(message, from);
            } else {                       // broadcast message
                for (key in participants) {
                    if (participants[key] !== from) {
                        participants[key].receive(message, from);
                    }
                }
            }
        }
    };
};


function run() {


    var yoko = new Participant("Yoko");
    var john = new Participant("John");
    var paul = new Participant("Paul");
    var ringo = new Participant("Ringo");


    var chatroom = new Chatroom();
    chatroom.register(yoko);
    chatroom.register(john);
    chatroom.register(paul);
    chatroom.register(ringo);


    yoko.send("All you need is love.");
    yoko.send("I love you John.");
    john.send("Hey, no need to broadcast", yoko);
    paul.send("Ha, I heard that!");
    ringo.send("Paul, what do you think?", paul);
}

09、Observer

Observer模式提供了一種訂閱模型,其中對(duì)象訂閱一個(gè)事件并在事件發(fā)生時(shí)得到通知。這種模式是事件驅(qū)動(dòng)編程的基石,包括 JavaScript。Observer模式促進(jìn)了良好的面向?qū)ο笤O(shè)計(jì)并促進(jìn)了松散耦合。

圖片

function Click() {
    this.handlers = [];  // observers
}


Click.prototype = {


    subscribe: function (fn) {
        this.handlers.push(fn);
    },


    unsubscribe: function (fn) {
        this.handlers = this.handlers.filter(
            function (item) {
                if (item !== fn) {
                    return item;
                }
            }
        );
    },


    fire: function (o, thisObj) {
        var scope = thisObj || window;
        this.handlers.forEach(function (item) {
            item.call(scope, o);
        });
    }
}


function run() {


    var clickHandler = function (item) {
        console.log("fired: " + item);
    };


    var click = new Click();


    click.subscribe(clickHandler);
    click.fire('event #1');
    click.unsubscribe(clickHandler);
    click.fire('event #2');
    click.subscribe(clickHandler);
    click.fire('event #3');
}

10、Visitor

Visitor模式定義了對(duì)對(duì)象集合的新操作,而不更改對(duì)象本身。新邏輯駐留在一個(gè)名為 Visitor 的單獨(dú)對(duì)象中。

圖片

var Employee = function (name, salary, vacation) {
    var self = this;


    this.accept = function (visitor) {
        visitor.visit(self);
    };


    this.getName = function () {
        return name;
    };


    this.getSalary = function () {
        return salary;
    };


    this.setSalary = function (sal) {
        salary = sal;
    };


    this.getVacation = function () {
        return vacation;
    };


    this.setVacation = function (vac) {
        vacation = vac;
    };
};


var ExtraSalary = function () {
    this.visit = function (emp) {
        emp.setSalary(emp.getSalary() * 1.1);
    };
};


var ExtraVacation = function () {
    this.visit = function (emp) {
        emp.setVacation(emp.getVacation() + 2);
    };
};


function run() {


    var employees = [
        new Employee("John", 10000, 10),
        new Employee("Mary", 20000, 21),
        new Employee("Boss", 250000, 51)
    ];


    var visitorSalary = new ExtraSalary();
    var visitorVacation = new ExtraVacation();


    for (var i = 0, len = employees.length; i < len; i++) {
        var emp = employees[i];


        emp.accept(visitorSalary);
        emp.accept(visitorVacation);
        console.log(emp.getName() + ": $" + emp.getSalary() +
            " and " + emp.getVacation() + " vacation days");
    }
}

結(jié)論

當(dāng)我們結(jié)束我們的 JavaScript 設(shè)計(jì)模式之旅時(shí),很明顯這些強(qiáng)大的工具在制作可維護(hù)、可擴(kuò)展和高效的代碼方面發(fā)揮著至關(guān)重要的作用。

通過理解和實(shí)施這些模式,您不僅會(huì)提升您的編程技能,還會(huì)為您自己和您的團(tuán)隊(duì)成員創(chuàng)造更愉快的開發(fā)體驗(yàn)。

請(qǐng)記住,設(shè)計(jì)模式不是一種放之四海而皆準(zhǔn)的解決方案。分析項(xiàng)目的獨(dú)特需求和約束以確定哪些模式將帶來最大價(jià)值至關(guān)重要。

不斷學(xué)習(xí)和試驗(yàn)不同的設(shè)計(jì)模式將使您能夠做出明智的決策并為您的項(xiàng)目選擇最佳方法。

將設(shè)計(jì)模式整合到您的工作流中可能需要投入時(shí)間和精力,但從長(zhǎng)遠(yuǎn)來看,這是值得的。

當(dāng)您掌握編寫優(yōu)雅、模塊化和高效的 JavaScript 代碼的藝術(shù)時(shí),您會(huì)發(fā)現(xiàn)您的應(yīng)用程序變得更加健壯,您的調(diào)試過程更易于管理,并且您的整體開發(fā)體驗(yàn)更加愉快。

因此,繼續(xù)探索 JavaScript 設(shè)計(jì)模式的世界,并希望您的代碼更易于維護(hù)、可擴(kuò)展和高效。

責(zé)任編輯:華軒 來源: web前端開發(fā)
相關(guān)推薦

2025-02-10 08:30:00

JavaScrip開發(fā)設(shè)計(jì)模式

2024-09-03 10:40:38

2024-01-22 08:15:42

API協(xié)議設(shè)計(jì)

2023-06-18 12:21:42

分布式系統(tǒng)模式架構(gòu)設(shè)計(jì)

2017-12-11 16:25:25

2024-09-02 10:07:52

2024-03-26 13:35:19

模型架構(gòu)框架

2016-03-18 07:21:56

網(wǎng)站體驗(yàn)設(shè)計(jì)錯(cuò)誤

2021-02-19 14:07:03

JavaScript編程開發(fā)

2024-01-02 11:38:41

體驗(yàn)交互設(shè)計(jì)

2010-09-07 13:12:17

2024-11-13 13:20:44

2019-08-15 14:11:31

LVS負(fù)載均衡調(diào)度算法

2017-10-13 15:33:51

字體App Android

2019-04-29 09:00:00

數(shù)據(jù)可視化JavaScript圖表庫

2023-05-15 20:08:04

Linux字體

2018-09-25 23:21:13

2010-07-16 16:45:56

職場(chǎng)培訓(xùn)

2024-08-22 08:54:40

2010-07-07 11:30:16

UML十種圖
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)