文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

十种 JavaScript 设计模式

2024-11-30 14:43

关注

在本教程中,我为每个 GoF 模式提供了 JavaScript 示例。大多数情况下,它们遵循原始图案设计的结构和意图。这些示例演示了每种模式背后的原则,但并未针对 JavaScript 进行优化。

01.Abstract Factory 

Abstract Factory创建由共同主题相关的对象。在面向对象编程中,工厂是创建其他对象的对象。抽象工厂抽象出新创建的对象共享的主题。

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 模式允许客户端仅通过指定类型和内容来构建复杂对象,细节完全对客户隐藏。

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 按照客户的指示创建新对象。在 JavaScript 中创建对象的一种方法是使用 new 运算符调用构造函数。 

然而,在某些情况下,客户端不知道或不应知道要实例化多个候选对象中的哪一个。 

Factory Method 允许客户端委托对象创建,同时仍然保留对要实例化的类型的控制。

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模式将一个接口(对象的属性和方法)转换为另一个接口。Adapter允许编程组件协同工作,否则由于接口不匹配而无法协同工作。适配器(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模式动态地扩展(装饰)对象的行为。在运行时添加新行为的能力是由 Decorator 对象实现的,它“将自身包装”在原始对象周围。多个装饰器可以向原始对象添加或覆盖功能。

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 模式提供了一个接口,使客户免受一个或多个子系统中复杂功能的影响。这是一个看似微不足道但功能强大且极其有用的简单模式。它通常出现在围绕多层架构构建的系统中。

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

代理模式为另一个对象提供代理或占位符对象,并控制对另一个对象的访问。

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模式通过封装这些对象的交互方式来提供对一组对象的集中管理权。此模型对于需要管理复杂条件的场景很有用,在这种情况下,每个对象都知道组中任何其他对象的任何状态更改。

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模式提供了一种订阅模型,其中对象订阅一个事件并在事件发生时得到通知。这种模式是事件驱动编程的基石,包括 JavaScript。Observer模式促进了良好的面向对象设计并促进了松散耦合。

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模式定义了对对象集合的新操作,而不更改对象本身。新逻辑驻留在一个名为 Visitor 的单独对象中。

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");
    }
}

结论

当我们结束我们的 JavaScript 设计模式之旅时,很明显这些强大的工具在制作可维护、可扩展和高效的代码方面发挥着至关重要的作用。

通过理解和实施这些模式,您不仅会提升您的编程技能,还会为您自己和您的团队成员创造更愉快的开发体验。

请记住,设计模式不是一种放之四海而皆准的解决方案。分析项目的独特需求和约束以确定哪些模式将带来最大价值至关重要。

不断学习和试验不同的设计模式将使您能够做出明智的决策并为您的项目选择最佳方法。

将设计模式整合到您的工作流中可能需要投入时间和精力,但从长远来看,这是值得的。

当您掌握编写优雅、模块化和高效的 JavaScript 代码的艺术时,您会发现您的应用程序变得更加健壮,您的调试过程更易于管理,并且您的整体开发体验更加愉快。

因此,继续探索 JavaScript 设计模式的世界,并希望您的代码更易于维护、可扩展和高效。

来源:web前端开发内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯