应对需求上的变更
- 观察者模式
目的:减少对象见的耦合,来提高扩展性
应用场景:当两个模块直接沟通会增加他们的耦合性时
2.职责链模式
目的:为了避免请求发送者与多个请求处理者耦合在一起,形成一个链条
应用场景:把操作分割成一系列模块,每个模块只处理自己的事情
3.访问者模式
目的:解耦数据结构与数据操作
应用场景:数据结构不希望与操作有关联
基本结构
观察者模式的基本结构
定义一个中转观察者,两个模块之间不直接沟通,而是通过观察者。一般适用于不方便直接沟通,或者异步操作。
function observe(){
this.message ={};
}
observe.prototype.regist = function(type,fn){
this.message[type] = fn;
}
observe.prototype.fire = function(type){
this.message[type]();
}
observe.prototype.remove = function(type,fn){
this.message[type] = null;
}
职责链模式的基本结构
把要做的事情组织为一条有序的链条,通过在这条链条传递消息来完成功能。适用于不涉及到复杂异步的操作
function mode1(){
}
function mode2(){
}
function mode3(){
}
_result=mode1(_result);
_result=mode2(_result);
_result=mode3(_result);
访问者模式的基本结构
通过定义一个访问者,代替直接访问对象,来减少两个对象之间的耦合
var data = {};
var handler = function(){
}
handler.prototype.get = function(){
}
var vistor = function(handler,data){
handler.get(data);
}
应用示例
观察者模式的示例
1.多人合作的问题
需求:现在假设A工程师写了首页模块,然后B工程师写了评论模块,现在要把评论展示在首页
function observe(){
this.message ={};
}
observe.prototype.regist = function(type,fn){
this.message[type] = fn;
}
observe.prototype.fire = function(type){
this.message[type]();
}
observe.prototype.remove = function(type,fn){
this.message[type] = null;
}
var observeOb = new observe();
function comment(){
var self = this;
this.commentList = [
{
type:'hot',
content:'xxx'
}
]
observeOb.regist('getHot',function(){
var _arr = [];
self.commentList.forEach((item) => {
if(item.type == 'hot'){
_arr.push(item);
}
})
return _arr;
})
}
function index(){
var _arr = observeOb.fire('getHot')
}
2.一个转盘
需求:有一个转盘应用,没转一圈,速度加快
function observe(){
this.message ={};
}
observe.prototype.regist = function(type,fn){
this.message[type] = fn;
}
observe.prototype.fire = function(type){
this.message[type]();
}
observe.prototype.remove = function(type,fn){
this.message[type] = null;
}
var observeOb = new observe();
//初始化html -> 最终结果选定 -> 运动效果 -> 运动控制
function htmlInit(target){
for(var i=0;i<9;i++){
var _div = document.createElement('div');
_div.innerHTML = i;
target.appendChild(_div);
_domArr.push(_div);
}
}
function getFinal(){
var _num = Math.random()*10+40;
return Math.floor(_num,0);
}
//{moveTime:10,speed:50}
function mover(moveConfig){
var nowIn = 0;
var removeNum = 9;
var timer = setInterval(() => {
if(nowIn != 0){
removeNum = nowIn - 1;
}
_domArr[removeNum].setAttribute('class','item');
_domArr[nowIn].setAttribute('class','item item-on');
nowIn++;
if(nowIn == moveConfig.moveTime){
clearInterval(timer);
if(moveConfig.moveTime == 10){
observeOb.fire('finish');
}
}
},moveConfig.speed);
}
function moveControll(){
var final = getFinal();
var _circle = Math.floor(final/10,0);
var stipNum = final%10;
var _speed = 2000;
var _runCircle=0;
move({
moveTime:10,
speed:_speed
})
observeOb.regist('finish',function(){
var _time=0;
_speed-=50;
_runCircle++;
if(_runCircle<=_circle){
_time = 10;
}else{
_time = stopNum;
}
move({
moveTime:_time,
speed:_speed
})
})
}
htmlInit(document.getElementById('app'));
moveControll();
职责链模式的示例
1.Axios的拦截器
需求:axios拦截器的设计,大家可以看成一个用给职责链的思想去处理请求
function axios(){
this.interceptors = {
request:new this.interceptorsManner(),
response:new this.interceptorsManner(),
}
}
axios.prototype.request = function(){
var chain = [dispathRequest,undefined];
var promise = Promise.resolve(config);
this.interceptors.request.handlers.forEach((interceptor) => {
chain.unshift(interceptor.fulfilled,interceptor.rejected);
})
this.interceptors.response.handlers.forEach((interceptor) => {
chain.push(interceptor.fulfilled,interceptor.rejected);
})
while(chain.length){
promise = promise.then(chain.shift(),chain.shift())
}
}
function interceptorsManner(){
this.handlers = [];
}
interceptorsManner.prototype.use = function(fulfilled,rejected){
this.handlers.push({
fulfilled:fulfilled,
rejected:rejected
})
}
2.利用职责链组织一个表单验证
需求:有一个表单,需要先前台校验,在后端校验
//表单事件绑定 -> 表单前端验证 -> 表单后端验证
//好处:随时可以在中间加入新的验证方法
//思想:把你要做的事情拆分成模块,模块之间只做自己模块的事情
InputDeviceInfo.onblur=function(){
var _value = input.value;
var _arr = [font,back];
async function test(){
var _result = _value;
while(_arr.length > 0){
_result = await _arr.shift()(_result);
}
return _result;
}
test().then((res)=>{
console.log(res);
})
}
function font(result){
}
function back(){
}
访问者模式的示例
1.不同角色访问数据
需求:假设有一个公司的财务报表。财务关心支出和收入,老板关心盈利
function report(){
this.income = ""
this.const=""
this.profit=""
}
function boss(){
}
boss.prototype.get = function(data){
}
function account(){
}
account.prototype.get = function(num1,num2){
}
function vistor(data,man){
var handle={
boss:function(data){
man.get(data.profit);
},
account:function(data){
man.get(data.income,data.cost);
}
}
handle[man.constructor.name](data);
}
vistor(new report(),new boss());
vistor(new report(),new account());
2.表格操作
需求:一个可以新增,删除的表格
function table(){
}
table.prototype.show = function(){
}
table.prototype.delete = function(){
vistor(this,tableData,'delete',id)
}
table.prototype.add = function(){
}
var tableData = [{
id:1,
name:'xxx',
price:'xxx'
}];
function vistor(table,data,handle){
var handleOb = {
delete:function(id){
},
add:function(id,name,price){
}
}
var arg = Array.prototype.splice(arguments);
arguments.splice(0,3);
handleOb[handle].apply(this,arg);
}
课程小结
1.观察者模式
适用于不适合直接沟通的模块之间的组织
2.职责链模式
组织同步模块,把要做的事情划分为模块,要做的事情一次传递
3.访问者模式
解耦数据操作与数据结构