js 设计模式 --- 前端
js中常见设计模式
- 工厂模式
一个工厂能提供一个创建对象的公共接口,我们可以在其中指定我们希望被创建的工厂对象的类型。
简单工厂模式:使用一个类来生成实例
var BicycleShop = function () { };
BicycleShop.prototype = {
sellBicycle: function (model) {
var bicycle;
switch (model) {
case "A"://A类型的自行车
bicycle = new A();
break;
case "B":
bicycle = new B();
break;
case "C":
bicycle = new C();
break;
}
return bicycle;
}
}
复杂工厂模式:使用子类来决定一个变量成员应该为哪个具体的类的实例;
将BicycleShop设计为一个抽象类,让子类根据各自的进货渠道实现其进货自行车(createBicycle)的工作:
var BicycleShop = function(){};
BicycleShop.prototype = {
sellBicycle : function(model){
//让其子类来完成这个工作
var bicycle = this.createBicycle(model);
return bicycle;
},
//抽象方法,必须实现后才能调用
createBicycle : function(model){
throw new Error("必须通过子类的实例才能调用此方法,进货自行车");
}
};
此时
BicycleShop类中定义了一个createBicycle方法,该方法一旦调用就会抛出异常,因此,该类是不能直接实例化的,该抽象类必须被继承,通过其子类来完成createBicycle的工作。
实现工厂模式
//Oracle自行车商店
var OracleBicycleShop = function(){};
//继承父类
inherits(OracleBicycleShop,BicycleShop);
//实现createBicycle方法
OracleBicycleShop.prototype.createBicycle = function(model){
var bicycle;
//生产自行车
switch(model){
case "speedster":
bicycle = new OracleSpeedster();
break;
case "lowrider":
bicycle = new OracleLowrider();
break;
case "Alien":
bicycle = new OracleAlien();
break;
case "comfort cruiser":
default :
bicycle = new OracleComfortCruiser();
}
return bicycle;
};
//IBM自行车商店
var IBMBicycleShop = function(){};
//继承父类
inherits(IBMBicycleShop,BicycleShop);
//实现createBicycle方法
IBMBicycleShop.prototype.createBicycle = function(model){
var bicycle;
//生产自行车
switch(model){
case "speedster":
bicycle = new IBMSpeedster();
break;
case "lowrider":
bicycle = new IBMLowrider();
break;
case "Alien":
bicycle = new IBMleAlien();
break;
case "comfort cruiser":
default :
bicycle = new IBMComfortCruiser();
}
return bicycle;
};
通过对父类的继承,根据需求创建新的子类和实现createBicycle;
//到Oracle专卖店购买
var oracle = new OracleBicycleShop();
var yourNewBicycle = oracle.createBicycle("speedster");
//到IBM专卖店购买
var ibm = new IBMBicycleShop();
var myNewBicycle = ibm.createBicycle("speedster");
- 单例模式
两个特点:一个类只有一个实例,并且提供可全局访问点 全局对象是最简单的单例模式:window
demo:登录弹出框只需要实例化一次,就可以反复用了
//单例模式抽象,分离创建对象的函数和判断对象是否已经创建
var getSingle = function (fn) {
var result;
return function () {
return result || ( result = fn.apply(this, arguments) );
}
};
- 模块模式
模块模式的思路是为单体模式添加私有变量和私有方法能够减少全局变量的使用
demo:返回对象的匿名函数。在这个匿名函数内部,先定义了私有变量和函数
var demo = (function(){
var num = 1; //私有变量
function aFu (){ //私有函数
//业务逻辑
}
return {
publicMethod1, //返回一个对象
publicMethod2 //包含公有方法和属性
}
}
- 代理模式
代理对象可以代替本体被实例化,并使其可以被远程访问
demo: 虚拟代理实现图片的预加载
class MyImage {
constructor() {
this.img = new Image()
document.body.appendChild(this.img)
}
setSrc(src) {
this.img.src = src
}
}
class ProxyImage {
constructor() {
this.proxyImage = new Image()
}
setSrc(src) {
let myImageObj = new MyImage()
myImageObj.img.src = 'file://xxx.png' //为本地图片url
this.proxyImage.src = src
this.proxyImage.onload = function() {
myImageObj.img.src = src
}
}
}
var proxyImage = new ProxyImage()
proxyImage.setSrc('http://xxx.png') //服务器资源url
- 缓存模式
缓存代理的含义就是对第一次运行时候进行缓存,当再一次运行相同的时候,直接从缓存里面取,这样做的好处是避免重复一次运算功能,如果运算非常复杂的话,对性能很耗费,那么使用缓存对象可以提高性能;
- 命令模式
有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道请求的操作是什么,此时希望用一种松耦合的方式来设计程序代码;使得请求发送者和请求接受者消除彼此代码中的耦合关系。
- 模板方法模式
一、模板方法模式:一种只需使用继承就可以实现的非常简单的模式。
二、模板方法模式由两部分组成,第一部分是抽象父类,第二部分是具体的实现子类。
- 策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换
- 发布订阅者模式
发布—订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
var list = {
arr: [],
subscribe: function(fn) {
this.arr.push(fn);
},
notify: function() {
this.arr.forEach(fn => fn());
}
};
var fn1 = function() {
console.log(1)
}
var fn2 = function() {
console.log(2)
}
list.subscribe(fn1);
list.subscribe(fn2);
list.notify();
- 中介者模式
中介者模式的作用是解除对象与对象之间的耦合关系,增加一个中介对象后,所有的相关对象都通过中介者对象来通信,而不是相互引用,所以当一个对象发送改变时,只需要通知中介者对象即可。中介者使各个对象之间耦合松散,而且可以独立地改变它们之间的交互。
- 装饰者模式
动态的给类或对象增加职责的设计模式。
装饰器模式并不去深入依赖于对象是如何创建的,而是专注于扩展它们的功能这一问题上。装饰器模式相比生成子类更为灵活。
var Car = function() {}
Car.prototype.drive = function() {
console.log('乞丐版');
}
var AutopilotDecorator = function(car) {
this.car = car;
}
AutopilotDecorator.prototype.drive = function() {
this.car.drive();
console.log('启动自动驾驶模式');
}
var car = new Car();
car = new AutopilotDecorator(car);
car.drive(); //乞丐版;启动自动驾驶模式;
- 适配器模式
适配器模式主要解决两个接口之间不匹配的问题,不会改变原有的接口,而是由一个对象对另一个对象的包装。
demo:两个地图(2个类),他们有一个共同方法但是名字不同,这时候需要定义适配器类, 对其中的一个类进行封装。
class GooleMap {
show() {
console.log('渲染谷歌地图')
}
}
class BaiduMap {
display() {
console.log('渲染百度地图')
}
}
// 定义适配器类, 对BaiduMap类进行封装
class BaiduMapAdapter {
show() {
var baiduMap = new BaiduMap()
return baiduMap.display()
}
}
function render(map) {
if (map.show instanceof Function) {
map.show()
}
}
render(new GooleMap()) // 渲染谷歌地图
render(new BaiduMapAdapter()) // 渲染百度地图
- 外观模式
一种相对简单而又无处不在的模式。外观模式提供一个高层接口,这个接口使得客户端或子系统更加方便调用。
let getName = function (){
return "xiaoming"
}
let getAge = function () {
return 18
}
需要调用上面2个函数时候,可以用更高层的接口去调用
let getPersonInfo = function () {
return info = getName() + getAge();
}

浙公网安备 33010602011771号