A super detailed introduction to js design patterns
<br>
The content of this article is a very detailed introduction to js design patterns. It has certain reference value. Friends in need can refer to it
js design pattern
<br>
##Jan 14, 2017 |<br>
Table of Contents- Preface
- Single Mode
- Factory Mode
- Iterator pattern
- Decorator pattern ##Strategy pattern
- Appearance mode
- Agent mode
- Mediator mode
- Observer mode
- Preface
<br>This article refers to "javascript mode", so a lot of the content will be the same as in the book. I have this book in hand. Friends who are book readers can read the book directly. Because my memory habit is to copy books, I will copy them down first and then post them on the blog.
Single Mode
The idea of the single mode is to ensure that there is only one instance of a specific class, which means that when you use the same class for the second time to create an object, you should get the same result as the first The objects created are exactly the same.
Method 1
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 |
<br> |
<br> |
function Universe(){ var instance=this; //缓存this this.xx="xx"; Universe=function(){ //重写此构造函数 return instance; } } var uni=new Universe(); var uni2=new Universe(); uni===uni2; //true <br> |
缺点
因为重写了构造函数,constructor 还是指向了老的构造函数,且实例化后在添加原型属性也是不一样的。如下
<br> |
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 <br> |
方法三
解决方法二问题。
<br> <br> |
function Universe(){ var instance; Universe=function Universe(){ return instance ; } Universe.prototype=this; //保存原型属性 instance=new Universe(); instance.constructor=Universe; instance.xx="xx"; } <br> |
方法四
自运行函数。
<br> |
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 <br> |
工厂模式
工厂模式是为了创建对象。
例子
公共构造函数 CarMaker
名为factory的CarMaker静态方法来创建car对象
<br> |
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 <br> |
实现
<br> <br> |
<br> 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 <br> |
内置工厂对象
Object() 构造函数即为内置工厂对象。
迭代器模式
有一个包含某种数据集合的对象,该数据可能存储在一个复杂数据结构内部,而要提供一个简单方法讷讷感访问到数据结构中没一个元素。
next() 下一个
hasNext() 是否有下一个
reWind() 重置指针
current() 返回当前
<br> <br> |
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 <br> |
装饰者模式
可以在运行时候添加附加功能到对象中,他的一个方便特征在于其预期行为的可定制和可配置特性。
例子 假设在开发一个销售商品的Web应用,每一笔信销售都是一个人新的 sale 对象。该对象“知道”有关项目的价格,并可以通过 getPrice() 方法返回加个。<br>根据不同情况,可以用额外的功能装饰此对象。<br>假设客户在魁北克省,买房需要支付联邦税和魁北克省税,则此时需要调用联邦税装饰者和魁北克省税装饰者。
<br> |
var sale=new Sale(100); sale=sale.decorate("fedtax"); //联邦税 sale=sale.decorate("quebec"); //魁北克省税 sale=sale.decorate("miney"); //转为美元格式 sale.getPrice(); //返回价格 <br> |
并且装饰是可选的,例如不再魁北克省有可能没有省税。
方法一
<br> |
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 <br> |
方法二
此方法使用列表实现,而且相对来说比较好理解一点。本质就是把装饰者名称保存到一个列表中并且一次调用此列表中的方法。
<br> <br> |
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 <br> |
策略模式
策略模式支持在运行时候选择算法。例如用在表单验证问题上,可以创建一个具有 validate() 方法的验证器对象,无论表单具体类型是什么,该方法都会被调用,<br>并且返回结果或者错误信息。
<br> <br> |
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")); } <br> |
策略模式定义及例子实现参考与《javascript模式》及 汤姆大叔的博客
外观模式
外观模式即让多个方法一起被调用
例如。 stopPropagation() 和 preventDefault() 兼容性一起调用。
<br> <br> |
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; } } } <br> |
代理模式
在代理模式中,一个对象充当另外一个对象的接口,和外观模式区别是:外观模式是合并调用多个方法。<br>代理模式是介于对象的客户端和对象本身之间,并且对该对象的访问进行保护。
包裹例子
现在有个包裹,卖家要把这个包裹寄给gary,则需要通过快递公司寄过来,此时快递公司就是一个 proxy
<br> <br> |
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你的包裹:键盘 <br> |
论坛权限管理例子
本例子参考与 大熊君
权限列表
发帖 1
帖子审核 2
删帖 3
留言、回复 4
用户 | 代码 | 权限 |
---|---|---|
注册用户 | 001 | 1 4 |
论坛管理员 | 002 | 2 3 4 |
系统管理员 | 003 | 1 2 3 4 |
游客 | 000 | null |
用户类
<br> <br> |
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() { //留言回复 }; <br> |
论坛类
<br> <br> |
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; } }; <br> |
运行
<br> <br> |
new Forum(new User("administartor","003")); <br> |
中介者模式
中介者模式可以让多个对象之间松耦合,并降低维护成本
例如:游戏程序,两名玩家分别给与半分钟时间来竞争决出胜负(谁按键的次数多胜出,这里玩家1按1,玩家2按0)
计分板(scoreboard)
中介者 (mediator)
中介者知道所有其他对象的信息。他与输入设备(此时是键盘)进行通信并处理键盘上的按键时间,之后还将消息通知玩家。玩家玩游戏同时(每一分都更新自己分数)还要<br>通知中介者他所做的事情。中介者将更新后的分数传达给计分板。
除了中介者莫有对象知道其他对象。
A super detailed introduction to js design patterns
<br> <br> |
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); <br> |
Observer Pattern
The observer pattern is very widely used in javascript. All browser time is the implementation of this mode, and events in node.js are also the implementation of this mode. <br>Another name for this mode is Subscription/Publishing Mode
. <br>The reason for designing this pattern is to promote the formation of loose coupling. In this pattern, it is not that one object calls the method of another object, but that one object subscribes to the <br>specific activity of another object and changes the state after Get notified. Subscribers therefore also become observers, and the observed objects become publishers or topics. When an important event occurs<br>The publisher will notify (call) all subscribers and may often deliver messages in the form of event objects.
Summary
1. Singleton mode
Create only one object for a class.
2.Factory pattern
A method to create objects at runtime based on a string specification type.
3. Iterator pattern
Provides an API to traverse or operate complex custom data structures.
4. Decorator pattern
Adjust objects at runtime by adding functionality from predefined decorator objects
5. Strategy pattern
Still maintaining the same interface while hanging on the best strategy to handle a specific task.
6. Appearance pattern
always provides a more convenient API by wrapping common methods into a new method.
7. Proxy mode
Control access to an object by wrapping it. The main method is to aggregate the directions into rents or <br>Only perform access when really necessary. High operational overhead is never avoided.
8. Terminator pattern
Through this, your objects do not "talk" to each other directly, but communicate with each other through an intermediary, <br> thus forming loose coupling. .
9. Observer pattern
By creating an "observable" object, when an event of interest occurs, the time can be notified to all observers<br>, thus forming loose coupling .
The above is the detailed content of A super detailed introduction to js design patterns. For more information, please follow other related articles on the PHP Chinese website!

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 English version
Recommended: Win version, supports code prompts!

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft
