其实在初学前端时,并没有太过于在意设计模式这一码子事。因为追求效率之上,其实这些基础还是很重要的,如果不好好打好基础,养成野路子的思维,对于js这么灵活的语言,在一些地方会感到之分的痛苦!!!
这里首先介绍一下几种设计模式
单例模式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
实现方法:先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,
这就确保了一个类只有一个实例对象。
适用场景:一个单一对象。
比如一个网站的登录,点击登录后弹出一个登录弹框,即使再次点击,
也不会再出现一个相同的弹框。
var Singleton = function(name) {
this.name = name;
//一个标记,用来判断是否已将创建了该类的实例
this.instance = null;
}
// 提供了一个静态方法,用户可以直接在类上调用
Singleton.getInstance = function(name) {
// 没有实例化的时候创建一个该类的实例
if(!this.instance) {
this.instance = new Singleton(name);
}
// 已经实例化了,返回第一次实例化对象的引用
return this.instance;
}
var a = Singleton.getInstance('sven1');
var b = Singleton.getInstance('sven2');
// 指向的是唯一实例化的对象
console.log(a === b);
JAVA:
public class Singleton {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class SingletonHolder{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static Singleton instance = new Singleton();
}
/**
* 私有化构造方法
*/
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
发布/订阅模式
定义:又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,
所有依赖于它的对象都将得到通知。
场景:订阅感兴趣的专栏和公众号。
https://www.baidu.com/link?url=pY2hsJFtbcLzyLlvVFibD8cYVzhZph0YWCTTQtOTU5XW2elTIpChnxHcpsfVXzWg&wd=&eqid=c8e482090048a121000000045d542916
https://blog.csdn.net/alisa_lisa/article/details/88537159
var pubsub = (()=>{
var topics = {};
function subscribe(topic,fn){
if(!topics[topic]){
topics[topic] = [];
}
topics[topic].push(fn);
}
function publish(topic,...args){
if(!topics[topic])
return;
for(let fn of topics[topic]){
fn(...args);
}
}
return {
subscribe:subscribe,
publish:publish
}
})()
pubsub.subscribe('test',function(a,b){ //订阅者A订阅了test事件
console.log(a,b);
});
pubsub.publish('test','123','HH'); //123 HH(发布者B发布了test事件)
策略模式
定义:将一个个算法(解决方案)封装在一个个策略类中。
优点:
策略模式可以避免代码中的多重判断条件。
策略模式很好的体现了开放-封闭原则,将一个个算法(解决方案)封装在一个个策略类中。
便于切换,理解,扩展。
策略中的各种算法可以重复利用在系统的各个地方,避免复制粘贴。
策略模式在程序中或多或少的增加了策略类。但比堆砌在业务逻辑中要清晰明了。
违反最少知识原则,必须要了解各种策略类,才能更好的在业务中应用。
应用场景:根据不同的员工绩效计算不同的奖金;表单验证中的多种校验规则。
代理模式
定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。
应用场景:图片懒加载(先通过一张loading图占位,然后通过异步的方式加载图片,
等图片加载好了再把完成的图片加载到img标签里面。)
中介者模式
定义:通过一个中介者对象,其他所有相关对象都通过该中介者对象来通信,而不是互相引用,
当其中的一个对象发生改变时,只要通知中介者对象就可以。可以解除对象与对象之间的紧耦合关系。
应用场景:例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,
都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
工厂方法模式
let factory = function (role) {
if(this instanceof factory) {
var s = new this[role]();
return s;
} else {
return new factory(role);
}
}
factory.prototype = {
admin: function() {
this.name = '平台用户';
this.role = ['登录页', '主页']
},
common: function() {
this.name = '游客';
this.role = ['登录页']
},
test: function() {
this.name = '测试';
this.role = ['登录页', '主页', '测试页'];
this.test = '我还有一个测试属性哦'
}
}
let admin = new factory('admin');
let common = new factory('common');
let test = new factory('test');
装饰者模式
定义:在不改变对象自身的基础上,在程序运行期间给对象动态的添加方法。
应用场景:有方法维持不变,在原有方法上再挂载其他方法来满足现有需求;函数的解耦,
将函数拆分成多个可复用的函数,再将拆分出来的函数挂载到某个函数上,实现相同的效果但增强了复用性。
var Plan1 = {
fire: function () {
console.log('发射普通的子弹');
}
};
var missileDecorator= function () {
console.log('发射导弹!');
};
var fire = Plan1.fire;
Plan1.fire=function () {
fire();
missileDecorator();
};
Plan1.fire();
懒加载怎么实现
实现:img标签src属性为空,给一个data-xx属性,里面存放图片真实地址,
当页面滚动直至此图片出现在可视区域时,用js取到该图片的data-xx的值赋给src。
webpack打包方式
把项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到项目的所有依赖文件,
使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。