Ⅰ- 壹 - 什么是设计模式 ?
原生 js 中没有设计模式,它是模仿 java 语言中的设计模式来实现。
设计模式分为三种类型,共23种。
- 创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
- 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
- 行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。
Ⅱ - 贰 - 工厂模式
工厂模式就是做一个对象创建的封装,并将创建的对象 return 出去。
工厂模式适用于:
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
工厂模式普通写法:
function CreateMan(name,age) {
var obj={};
obj.name=name;
obj.age=age;
obj.sayName=function () {
return this.name;
};
return obj;
}
var p1=CreateMan("zhangsan",20);
var p2=CreateMan("wangwu",30);
工厂模式复杂写法,每一个类都应该是一个单独的文件:
class CarFactory{
static get CAR(){
return "Car";
}
static get BUS(){
return "Bus";
}
static get TAXI(){
return "TAXI";
}
static createCar(type){
switch(type){
case CarFactory.CAR:
return new Car();
case CarFactory.BUS:
return new Bus();
case CarFactory.TAXI:
return new Taxi();
}
}
}
class Car{
constructor(){
}
getName(){
console.log("这是一个:"+this.constructor.name)
}
}
class Bus extends Car{
constructor(){
super();
}
}
class Taxi extends Car{
constructor(){
super();
}
}
var car1=CarFactory.createCar(CarFactory.BUS);
var car2=CarFactory.createCar(CarFactory.TAXI);
car1.getName();//这是一个:Bus
car2.getName();//这是一个:Taxi
Ⅲ - 叁 - 单例模式
单例模式就是运行完成后返回的对象是唯一的,如果已经创建出来就直接返回。
单例模式的普通写法:
var obj;
function getInstance(){
return obj || (obj={});
}
var s=getInstance();
var o=getInstance();
console.log(s===o);//true
单例模式的复杂写法:
//使用闭包的形式,防止在外部更改 _instance 的值
let ViewModel=(function(){
var _instance;
return class ViewModel{
constructor(){
}
static getInstance(){
if(!_instance) _instance=new ViewModel();
return _instance;
}
}
})();
var a=ViewModel.getInstance();
var b=ViewModel.getInstance();
console.log(a===b);//true
Ⅳ - 肆 - 构造器模式
构造器是一个当新建对象的内存被分配后,用来初始化该对象的一个特殊函数。对象构造器是被用来创建特殊类型的对象的,首先它要准备使用的对象,其次在对象初次被创建时,通过接收参数,构造器要用来对成员的属性和方法进行赋值。
function CreateMan(name,age) {
this.name=name;
this.age=age;
this.toString=function () {
return this.name+"年龄:"+this.age;
}
}
var p1=new CreateMan("zhangsan",20);
var p2=new CreateMan("wangwu",30);
console.log(p1.toString());
console.log(p2.toString());
Ⅴ - 伍 - 桥接模式
桥接模式可以理解为将抽象部分与它的实现部分分离,使它们都可以独立地变化。它的本质就是函数的封装,在实现api的时候,桥接模式非常常用。例如 some() 的实现过程,some函数并不关心 fn 里面的具体实现,fn 里面的逻辑也不会被 some 函数的改写影响。
var list = [1,2,3,4,5];
function some(arr,fn){
for(var i=0;i<arr.length;i++){
//如果数组的元素是空,则跳过
if(arr[i]===undefined) continue;
//如果fn()的返回结果是true,则返回true
if(fn(arr[i],i,arr)) return true;
}
//默认返回false
return false;
}
var s = some(list,function(item,index,arr){
return item>4
})
console.log(s);//true
Ⅵ - 陆 - 外观模式
外观模式是一种无处不在的模式,外观模式提供一个高层接口,这个接口使得客户端或者子系统调用起来更加方法。比如:这样就方便组装,如果一开始就把两个写到一个函数中,那就不能够只单独调用其中一个了。
function getName() {
return "xiaoming";
}
function getSex() {
return "man";
}
function getUserInfo() {
var info=getName()+getSex();
return info;
}
console.log(getUserInfo());
Ⅶ - 柒 - 代理模式
当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理之后,再把请求转交给本体对象。代理和本体的接口具有一致性,本体定义了关键功能,而代理是提供或拒绝对它的访问,或者在访问本体之前做一些额外的事情。
代理模式主要有三种:
- 保护代理,指拒绝访问主体;
- 虚拟代理,在控制对主体进行访问时,加入了一些额外的操作;
- 缓存代理,为一些数据大的运算结果提供暂时的缓存,提升效率(类似于闭包中的局部变量)。
// 主体,发送消息
function sendMsg(msg) {
console.log(msg);
}
// 代理,对消息进行过滤
function proxySendMsg(msg) {
// 无消息则直接返回,这是保护代理
if (typeof msg === "undefined") {
return;
}
// 有消息则进行过滤,这是虚拟代理
msg = ("" + msg).replace(/小朋友/g, '');
sendMsg(msg);
}
sendMsg('你好小朋友'); //你好小朋友
proxySendMsg('你好小朋友'); //你好
proxySendMsg();
Ⅷ - 捌 - 观察者模式
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态时,所有依赖于它的对象都会得到通知并被自动更新。通俗点理解,就是面试官是被观察者,而等待通知的人是观察者
观察者模式的三个步骤:添加至观察列表,从观察列表中移除,进行观察。
javascript中平时接触的dom事件,其实就是一种观察者模式的体现:
div.onclick=function click(){ console.log("click" ) }