理解javascript 桥接模式
桥接模式是指:将抽象和行为划分开来,从而将各个可能变化的维度分离开来,各自独立成一个类,但是能够动态的组合。
举个例子:实现每个角色的功能(简单说明,不做实际使用)
人 分为学生和老师两个角色,每个角色都有吃,跑,玩等功能类,如果实现每个角色有哪些功能
常规的做法:
为了简单说明问题,使用ES6来说明这个问题:
var role = function(){}
class student extends role {
sayName (){
console.log("我是学生");
}
}
class eatAction extends student{
startAction(){
console.log("吃了");
}
}
let s = new eatAction();
s.sayName(); //我是学生
s.startAction() //吃了
这种方式对于每增加一个角色类要增加三个功能类,每增加一个功能类,要增加两角色继承,所以对于复杂的角色和功能就会很繁琐
另一种方法:使用桥接模式,分成角色和功能两个维度
这这里使用ES5的方式来实现这个例子
//定义一个接口类
var Interface = function (name,methods) {
if(arguments.length!=2){
throw new Error('必须输入两个参数,当前个数'+arguments.length);
};
this.name = name; //接口名
this.methods = []; //函数名
for(var i=0;i<methods.length;i++){
if(typeof methods[i] !== 'string'){
throw new Error('方法名参数必须为string');
}else{
this.methods.push(methods[i]);
}
}
};
// 模仿接口
Interface.ensureImplements = function (object) {
if(arguments.length<2){
throw new Error('必须输入两个参数,当前个数' + arguments.length);
return;
};
for(var i =1;i<arguments.length;i++){
var interface = arguments[i];
if(interface.constructor != Interface){
throw new Error("接口没有实现");
};
for(var j=0;j<interface.methods.length;j++){
var method = interface.methods[j];
if(!object[method] || typeof object[method]!=='function'){
throw new Error("接口名:"+interface.name+"方法名:"+method+"没找到");
}
}
}
};
//继承的封装
function extend(subClass,superClass) {
var f = function () {};
f.prototype =superClass.prototype;
subClass.prototype = new f();
subClass.prototype.constructor = subClass;
subClass.superclass =superClass.prototype;
if(superClass.prototype.constructor==Object.prototype.constructor){
superClass.prototype.constructor =superClass;
}
};
/*
* 定义一个接口类
*
* */
var people =new Interface('people',['sayName']);
function Student() {
this.sayName=function () {
console.log("我是学生");
};
Interface.ensureImplements(this,people);
}
function Teacher() {
this.sayName=function () {
console.log("我是老师");
};
Interface.ensureImplements(this,people)
}
/*
*
* 定义一个抽象类
* */
function Action (){};
Action.prototype = {
role:null,
setRole:function (role) {
this.role = role;
},
startAction:function () {
throw new Error("该类是抽象类");
}
};
function eatAction() {
eatAction.superclass.constructor.call(this);
}
function runAction() {
runAction.superclass.constructor.call(this);
}
function playAction() {
playAction.superclass.constructor.call(this);
}
extend(eatAction,Action);
eatAction.prototype.startAction = function () {
this.role.sayName();
console.log("吃了");
};
extend(runAction,Action);
runAction.prototype.startAction = function () {
this.role.sayName();
console.log("跑了");
};
extend(playAction,Action);
playAction.prototype.startAction = function () {
this.role.sayName();
console.log("玩了");
};
//测试
var s = new Student();
var t = new Teacher();
var eat = new eatAction();
eat.setRole(s);
eat.startAction(); //我是学生 吃了
var run= new runAction();
run.setRole(t);
run.startAction(); //我是老师 跑了
这样角色和功能的增加只需要在分别增加就行了,不需要像第一种方法,增加太多的开销