最新文章专题视频专题问答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
当前位置: 首页 - 科技 - 知识百科 - 正文

JS常用设计模式

来源:动视网 责编:小采 时间:2020-11-27 20:03:22
文档

JS常用设计模式

JS常用设计模式:大型单页应用里,复杂度上升到一定程度时,没有适当的设计模式进行降耦,后续的开发也难以下手。而设计模式正是为了降耦而存在。单例模式单例模式的核心是确保只有一个实例,并且提供全局访问。特点满足单一职责原则 : 使用代理模式,不在构造函数中判断
推荐度:
导读JS常用设计模式:大型单页应用里,复杂度上升到一定程度时,没有适当的设计模式进行降耦,后续的开发也难以下手。而设计模式正是为了降耦而存在。单例模式单例模式的核心是确保只有一个实例,并且提供全局访问。特点满足单一职责原则 : 使用代理模式,不在构造函数中判断


大型单页应用里,复杂度上升到一定程度时,没有适当的设计模式进行降耦,后续的开发也难以下手。
而设计模式正是为了降耦而存在。

单例模式

单例模式的核心是确保只有一个实例,并且提供全局访问。

特点

满足“单一职责原则” : 使用代理模式,不在构造函数中判断是否已经创建过该单例;

满足惰性原则

应用

弹出登陆窗口。

实例

 var getSingle = function (fn) {
 var res;
 return function() {
 return res || (res = fn.apply(this, arguments));
 }
}

var createPopup() {
 var p = document.createElement('p');
 p.innerHTML = "Login window";
 p.style.display = "none"; 
 document.body.appendChild(p);
 return p;
}

var createLoginPopup = getSingle(createPopup); 
//create popup p here by using a given function, 满足两个原则 

document.getElementById("loginBt").onclick = function() {
 var popup = createLoginPopup();
 pop.style.display = "block";
}

构造函数模式

/**
 * 构造一个动物的函数 
 */
function Animal(name, color){
 this.name = name;
 this.color = color;
 this.getName = function(){
 return this.name;
 }
}
// 实例一个对象
var cat = new Animal('猫', '白色');
console.log( cat.getName() );

原型模式

function Person(){ 
}

Person.prototype.name = "bill";
Person.prototype.address = "GuangZhou";
Person.sayName = function (){
 alert(this.name); 
}

var person1 = new Person();
var person2 = new Person();
 
//测试代码
alert(person1.name); // bill
alert(person2.name); // bill
person1.sayName(); //bill
person2.sayName(); //bill

person1.name = "666";

alert(person1.name); // 666
alert(person2.name); // bill
person1.sayName(); //666
person2.sayName(); //bill

混合模式

/**
 * 混合模式 = 原型模式 + 构造函数模式
 */
function Animal(name, color){
 this.name = name;
 this.color = color;

 console.log( this.name + this.color)
}
Animal.prototype.getInfo = function(){
 console.log('名称:'+ this.name);
}

function largeCat(name, color){
 Animal.call(null, name, color);

 this.color = color;
}

largeCat.prototype = create(Animal.prototype);
function create (parentObj){
 function F(){}
 F.prototype = parentObj;
 return new F();
};

largeCat.prototype.getColor = function(){
 return this.color;
}
var cat = new largeCat("Persian", "白色");
console.log( cat )

工厂模式

工厂:函数内部产生b对象并返回。

1. 
function a(name){
 var b = new object();
 b.name = name;
 b.say = function(){
 alert(this.name);
 } 
 return b 
}
2. 
function Animal(opts){
 var obj = new Object();
 obj.name = opts.name;
 obj.color = opts.color;
 obj.getInfo = function(){
 return '名称:'+obj.name +', 颜色:'+ obj.color;
 }
 return obj;
}
var cat = Animal({name: '波斯猫', color: '白色'});
cat.getInfo();

简单工厂模式

简单工厂模式的理念就是创建对象,对不同类的实例化;只需要创建一个对象,然后通过对这个对象大量的方法和属性,并在最终将对象返回出来

//basketball base class 
var Baseketball = function(){ 
 this.intro = 'baseketball is hotting at unitedstates'; 
} 
Baseketball.prototype = { 
 getMember : function(){\ 
 console.log('each team needs five players'); 
 }, 
 getBallSize : function(){ 
 console.log('basketball is big'); 
 } 
} 
//football base class 
var Football = function(){ 
 this.intro = 'football is popular at all of the world'; 
} 
Football = function(){ 
 getMember = function(){ 
 
 }, 
 getBallSize = function(){ 
 
 } 
} 
//sport factory 
var SportsFactory = function(name){ 
 switch(name){ 
 case 'NBA': 
 return new Baseketball(); 
 case 'wordCup': 
 return new Football(); 
 } 
} 
 
//when you want football 
var football = SportsFactory('wordCup'); 
console.log(football); 
console.log(football.intro); 
football.getMember();

迭代器模式

装饰者模式

策略模式

定义一个个可以相互替换的算法,并且把他们封装起来。

特点

  1. 符合开放-封闭原则 : 要修改使用的算法时不用深入函数内部进行修改,只需修改策略类;

  2. 将算法的实现与使用分离开,提高算法复用性;

  3. 通过组合、委托和多态避免多重条件选择语句;

应用

动画实现不同的缓动效果。

一般分为两个部分:策略类于环境类。策略类用于封装各种算法,并且负责具体的计算过程; 环境类负责接收用户的请求,并且把请求委托给某一个策略类。因为各个策略类实现的算法和计算的结果不同,而环境类调用策略类的方法却是相同的,这就体现了多态性。要想实现不同的算法,只需要替换环境类中的策略类即可。

在js中,我们不必构造策略类,可直接使用函数作为策略对象。

示例

var strategies = {
 "s1": function() {
 //algo 1
 },
 "s2": function() {
 //algo 2
 }, 
 "s3": function() {
 //algo 3
 }
 }
 
 var someContext = new SomeConext();
 someContext.start("s1"); //using s1 to calculate
 //someContext.add("s1"); or add s1 as a rule for validation

外观模式

也可译为门面模式。它为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。引入外观角色之后,使用者只需要直接与外观角色交互,使用者与子系统之间的复杂关系由外观角色来实现,从而降低了系统的耦合度。
比如在家要看电影,需要打开音响,再打开投影仪,再打开播放器等等,引入外观角色之后,只需要调用“打开电影设备”方法就可以。外观角色封装了打开投影仪等操作,给使用者提供更容易使用的方法。

作用

  1. 简化复杂接口

  2. 解耦和,屏蔽使用者对子系统的直接访问

实例

在形式上,外观模式在javascript中就像这样:

function a(x){
 // do something
}
function b(y){
 // do something
}
function ab( x, y ){
 a(x);
 b(y);
}

下面的一个例子,把阻止冒泡和阻止默认事件放到了外观角色中:

var N = window.N || {};

N.tools = {
 stopPropagation : function( e ){
 if( e.stopPropagation ){
 e.stopPropagation();
 }else{
 e.cancelBubble = true;
 }
 },

 preventDefault : function( e ){
 if( e.preventDefault ){
 e.preventDefault();
 }else{
 e.returnValue = false;
 }
 },
 
 stopEvent : function( e ){
 N.tools.stopPropagation( e );
 N.tools.preventDefault( e );
 }

外观模式在javascript的应用主要可以分为两类,某块代码反复出现,比如函数a的调用基本都出现在函数b的调用之前,那么可以考虑考虑将这块代码使用外观角色包装一下来优化结构。还有一种就是对于一些浏览器不兼容的API,放置在外观内部进行判断,处理这些问题最好的方式便是将跨浏览器差异全部集中放置到一个外观模式实例中来提供一个对外接口。

代理模式

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

虚拟代理

虚拟代理是把一些开销很大的对象,延迟到真正需要它的时候才去创建执行

图片懒加载

//图片加载
let imageEle = (function(){
 let node = document.createElement('img');
 document.body.appendChild(node);
 return {
 setSrc:function(src){
 node.src = src;
 }
 }
})();

//代理对象
let proxy = (function(){
 let img = new Image();
 img.onload = function(){
 imageEle.setSrc(this.src);
 };
 return {
 setSrc:function(src){
 img.src = src;
 imageEle.setSrc('loading.gif');
 }
 }
})();

proxy.setSrc('example.png');

合并http请求

如果有一个功能需要频繁进行请求操作,这样开销比较大,可以通过一个代理函数收集一段时间内请求数据,一次性发出

//上传请求
let upload = function(ids){
 $.ajax({
 data: {
 id:ids
 }
 })
}

//代理合并请求
let proxy = (function(){
 let cache = [],
 timer = null;
 return function(id){
 cache[cache.length] = id;
 if(timer) return false;
 timer = setTimeout(function(){
 upload(cache.join(','));
 clearTimeout(timer);
 timer = null;
 cache = [];
 },2000);
 } 
})();
// 绑定点击事件
let checkbox = document.getElementsByTagName( "input" );
for(var i= 0, c; c = checkbox[i++];){
 c.onclick = function(){
 if(this.checked === true){
 proxy(this.id);
 }
 }
}

缓存代理

缓存代理可以作为一些开销大的运算结果提供暂时的存储,下次运算时,如果传递进来的参数跟之前一致,则可以直接返回前面存储的运算结果

//计算乘积
let mult = function(){
 let result = 1;
 for(let i = 0,len = arguments.length;i < len;i++){
 result*= arguments[i];
 }
 return result;
}

//缓存代理
let proxy = (function(){
 let cache = {};
 reutrn function(){
 let args = Array.prototype.join.call(arguments,',');
 if(args in cache){
 return cache[args];
 }
 return cache[args] = mult.apply(this,arguments);
 }
})();

优缺点

1.优点:代理模式能将代理对象与被调用对象分离,降低了系统的耦合度。代理模式在客户端和目标对象之间起到一个中介作用,这样可以起到保护目标对象的作用。代理对象也可以对目标对象调用之前进行其他操作。
2.缺点:增加了系统的复杂度

观察者模式

模块模式

/**
 * 模块模式 = 封装大部分代码,只暴露必需接口
 */
var Car = (function(){
 var name = '法拉利';
 function sayName(){
 console.log( name );
 }
 function getColor(name){
 console.log( name );
 }
 return {
 name: sayName,
 color: getColor
 }
})();
Car.name();
Car.color('红色');

文档

JS常用设计模式

JS常用设计模式:大型单页应用里,复杂度上升到一定程度时,没有适当的设计模式进行降耦,后续的开发也难以下手。而设计模式正是为了降耦而存在。单例模式单例模式的核心是确保只有一个实例,并且提供全局访问。特点满足单一职责原则 : 使用代理模式,不在构造函数中判断
推荐度:
标签: 模式 常用 js
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top