设计模式在JavaScript中用于在JavaScript的Web项目中解决一些常见问题的可重复解决方案。javascript
JavaScript设计模式是很是适合做为一种模式去提供问题的解决方案,但这并不能表明能够替代开发人员。java
结合开发人员的经验,设计模式能够帮助优化咱们的代码,而且寻求问题的解决方案和提供经常使用的解决方案,而不是片面的代码和语法。数据库
JavaScript设计模式能够协助开发人员写出有组织、优秀且良好结构的代码。
设计模式在使用中虽然很容易出现重复的状况,但却历来没法取代开发人员,相反,设计模式只能经过提供与指定问题关系不大的解决方案去防止开发中的大问题背景下的小问题,从而为开发人员提供帮助。设计模式
设计模式经过消除没必要要的重复代码来减小总体代码体积,从而使得咱们书写的代码更加健壮。bash
在本文中,我将介绍7种优秀、更受欢迎的JavaScript设计模式,它们总体属于三大类,建立型模式、结构型模式和行为型模式;app
这算得上是一种特殊的模式,它主要用于分配内存后初始化新建立的对象。
因为JavScript是一种面向对象语言,其每时每刻不在处理对象,所以我首先研究这个模式。ssh
一下是建立构造函数模式的一种写法。函数
var newObject = {}
var newObject = Object.create(Object.prototype)
var newObject = newObject()
复制代码
const object = new ConstructorObject();
复制代码
关键字new
告诉Javascript,ConstructorObject
应当是一个构造函数。
在这个模式中是不支持继承的。测试
原型模式是基于原型继承的,其建立的对象会充当其余对象的原型。其实,在创造对象时原型充当的是一个蓝图的角色。
示例优化
var myCar = {
name: 'Ford Escort',
brake: function() {
console.log('stop! I am applying branks');
},
Panic: function() {
console.log ( “wait. how do you stop thuis thing?”);
}
}
// 建立一个car实例
var youCar = Object.create(myCar);
console.log(youCar.name); // Ford Escort
复制代码
在模块设计模式中,是在原型模式上的一个改进。在模块模式中设置了不一样类型的修饰符(私有/共有)。能够建立类似的函数或属性而不会引发冲突。这在命名上具备灵活性,很差的是没法覆盖外部建立的函数。
示例
function AnimalContainer() {
const container = [];
function addAnimal(name) {
container.push(name);
}
function getAllAnimal() {
return container;
}
function removeAnimal(name) {
const index = container.indexOf(name);
if (index < 1) {
throw new Error('Animal not found in container');
}
container.splice(index, 1);
}
return {
add: addAnimal,
get: getAllAnimal,
remove: removeAnimal
}
}
const container = AnimalContainer();
// 添加
container.add('Hen');
container.add('Goat');
container.add('Sheep');
// 获取
console.log(container.get()); // ['Hen', 'Goat', 'Sheep']
// 移除
container.remove('Sheep');
console.log(container.get()); // ['Hen', 'Goat']
复制代码
当只须要建立一个实例时,好比数据库的链接,这一模式仍是很友好的。仅仅建立一个实例,当你肯定关闭链接或者打开实例时,确保已经关闭了以前的实例。这种模式也常常被称为严格模式,伴随着这种模式的一个缺点就是在测试时不友好,由于在测试时很难发现其依赖的隐藏起来的对象。
示例
function DatabaseConnection() {
let databaseInstance = null;
// 追踪在特定时间下建立的实例数
let count = 0;
function init() {
console.log(`opening database!#${count++}`);
}
function createInstance() {
if (databaseInstance === null) {
databaseInstance = init();
}
return databaseInstance;
}
function closeInstance() {
console.log('closing databse');
databaseInstance = null;
}
return {
open: createInstance,
close: closeIntance
}
}
const database = DatabaseConnection();
// 仅仅建立一个实例
database.open(); // opening database!#1
database.open(); // opening database!#1
database.open(); // opening database!#1
database.open(); // opening database!#1
database.close(); // close database
复制代码
这种模式一个建立对象的革新,再也不须要构造函数。它提供了一个通用的接口来建立对象,而且咱们还能够指定须要建立的工厂对象的类型。所以,咱们仅仅指定对象,工厂对象实例化并返回供咱们使用。同时当对象组件具备较为复杂时而且咱们想要根据不一样的环境去建立不一样的对象时,使用工厂模式时很是明智的。当使用许多须要共享的属性的轻对象以及组成须要解耦的对象时,咱们也可使用工厂模式。
示例
// Dealer A
DealerA = {};
DealerA.title = function title() {
return 'Dealer A';
}
DealerA.pay = function pay(amount) {
console.log('配置用户名: ${this.username} 密码: $ { this.password }');
return <code>Payment for service $${amount} is successful using ${this.title()}</code>;
};
// Dealer B
DealerB = {};
DealerB.title = function title() {
return 'DealerB';
}
DealerB.pay = function pay(amount) {
console.log('配置用户名: ${this.username} 密码: $ { this.password }');
return <code>Payment for service $${amount} is successful using ${this.title()}</code>;
}
function DealerFactory(DealerOption, config = {}) {
const dealer = Object.create(DealerOption);
Object.assign(dealer, config);
return dealer;
}
const dealerFactory = DealerFactory(DealerA, {
username: 'user',
password: 'password'
});
console.log(dealerFactory.title());
console.log(dealerFactory.pay(12));
const dealerFactory2= DealerFactory(DealerB, {
username: 'user',
password: 'password'
});
console.log(dealerFactory2.title());
console.log(dealerFactory2.pay(99));
复制代码
观察者模式在对象与其余对象集合通讯的时候使用仍是很方便的。在这个模式中,状态之间没有没必要要的push
和pull
操做,其所设计的模块仅修改数据的当前状态。
示例
function Observer() {
this.observerContainer = [];
}
Observer.prototype.subscribe = function (element) {
this.observerContainer.pssh(element);
}
// 从容器中移除一个元素
Observer.prototype.unsubscribe = function (element) {
const index = this.observerContainer.indexOf(element);
if (index !== -1) {
this.observerContainer.splice(index, 1);
}
}
Observer.prototype.notifyAll = function (element) {
this.observerContainer.forEach(function (observerElement) {
observerElement(element);
});
}
复制代码
在最后,我用命令模式结束了我对JavaScript设计模式的7种最佳总结。命令模式将方法的调用、操做或请求都封装到一个对象之中,便于咱们去思考地去调用。命令模式使咱们能够向正在执行的命令发布命令,并将责任委托到不一样的对象中。这些命令都以run()
、execute()
格式展现。
示例
(function () {
var carManager = {
requestInfo: function (model, id) {
return `the infomation for ${model} with ID ${id} is foo bar`;
},
buyVehicle: function (model, id) {
return `You have successfully purchased Item ${id}, a ${model}`;
},
arrangeViewing: function (model, id) {
return `You have successfully booked a viewing of ${model} (${id})`
}
};
})();
复制代码
对于咱们JavaScript开发人员来讲,这几种设计模式仍是颇有用的,维护性高的项目和减小开发周期中没必要要的工做是设计模式的主要优势。虽然JavaScript设计模式能够为复杂的问题提供解决方案和思路,可是设计模式代替开发人员的结论还是不恰当的。
在平常开发工做中,我经常使用命令模式,而其余模式虽然能够用到,但并不频繁。对于大多数开发者来讲,设计模式仅仅是提供了一种特定情景下的解决方案罢了,同时顺便也扩展了本身的思路。同时翻译不妥的地方还请指正,之后的翻译中会更加努力:)