目录
示例(多人合作问题、不同模块沟通,y型号的执行过程怎么办,转盘应用,下一圈减慢)
示例(axios的拦截器-不确定需求 、利用职责链组织一个表单验证)
提高整体项目可扩展性的核心
- 低耦合
- 良好的组织沟通方式
提高可扩展性的设计模式
架构-设计模块,并且组织模块沟通
观察者模式
目的:减少对象间的耦合,来提高扩展性
应用场景:当两个模块直接沟通会增加他们的耦合性时
// 无关组件互相传值 vuex eventbus
// a组件 -》 观察者 -》 b组件
// 事件绑定
// 执行 触发事件
// 设计模块
// 1.不好沟通-无关组件
// 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){ // 删除监听
this.message[type]=null;
}
示例(多人合作问题、不同模块沟通,y型号的执行过程怎么办,转盘应用,下一圈减慢)
/ 多人合作问题(观察者模式)(无关组件沟通)
// 需求:现在假设A工程师写了首页模块,然后B工程师写了评论模块。现在要把评论展示在首页
// a->首页
// b->评论
var observer = {// 不建议 ,变量权限,外部可直接调用 修改
message: {
},
regist: {
}
}
var observer = (function(){ // 推荐闭包
var _message = {} // 监听内容
return {
fire: function (type, data) {// 触发监听
_message[type](data);
},
regist: function (type, fn) {// 注册监听
return _message[type] = fn
}
}
})()
observer.regist('getComent', (data)=>{// 注册监听,data是收到的值
// 处理data,评论展示在首页
})
var commont = observeOb.fire('getComent', data);// 触发监听,评论内容data传到监听
//观察者模式-不同模块沟通
function observeOb(){
this.message={};// 储存观察内容的对象
}
observeOb.prototype.regist=function(type,fn){ // 注册监听
this.message[type]=fn;
}
observeOb.prototype.fire=function(type){ // 触发监听
this.message[type]();
}
function comment(){
var self=this;
this.commentList=[
{
type:'normal',
content:'xxxxx'
}
]
observeOb.regist('indexComment',function(){
var _arr=[];
self.commentList.forEach((item)=>{
if(item.type=='hot'){
_arr.push(_item);
}
})
return _arr;
})
}
function index(){
observeOb.fire('indexComment');
}
// y型号的执行过程怎么办
// 请求接口1-a
// 请求接口2-b
// 做某事 a*b
function observe(){
this.message={};// 储存观察内容的对象
}
observe.prototype.regist=function(type,fn){ // 注册监听
this.message[type]=fn;
}
observe.prototype.fire=function(type,data){ // 触发监听
this.message[type](data);
}
var arr = [];
observe.regist('finish', (data) => {
arr.push(data);
if (arr.length == 2) {
run(arr);
}
})
function mode1() {
setTimeout(()=>{
observe.fire('finish', 10)
}, Math.random() * 5000)// 1~5s
}
function mode2() {
setTimeout(()=>{
observe.fire('finish', 20)
}, Math.random() * 5000)// 1~5s
}
function run(arr) {
console.log(arr[0] & arr[1])
}
// 转盘应用,下一圈减慢
// 要做什么事
// 模块1:初始化转盘结构,
// 模块2:点击-》获取最终奖品,
// 模块3:转动控制模块(同步模块),
// 模块4:转动动画效果(异步模块,难通知控制模块)
// 300ms 转 10个奖品
// 观察者模式
var observer = (function(){ // 推荐闭包
var _message = {} // 监听内容
return {
fire: function (type, data) {// 触发监听
_message[type](data);
},
regist: function (type, fn) {// 注册监听
return _message[type] = fn
}
}
})()
// 1.初始化模块
var _domArr = []
function init(target) {
// 创建10个奖品
for(var i=0; i<=9; i++){
var _div = document.createElement('div');
_div.setAttribute("class","item");
_div.innerHTML=i;
target.appendChild(_div);
_domArr.push(_div);
}
}
// 1,2,3,4,5
// 2.获取最终奖品模块
function getFinal() {
var _num = Math.random() * 10 + 40; // 先转4圈,第五圈决定奖品
return Math.floor(_num, 0);
}
// 3.转动控制模块
function moveControll() {
var _speed = 50;
var final = getFinal();
var _circle = Math.floor(final/10,0)
var _runCircle = 0;//跑过的圈数
var stopNum = final % 10;
mover({
speed: _speed,
moveTime: 10 // 转动几个奖品
})
observer.regist('finish', () => {
var _movetime = 0; // 跑的格
_runCircle++;// 跑完一圈
_speed += 50;// 速度加50
if(_runCircle <= _circle) {
_movetime = 10;
} else {
_movetime = stopNum ;
}
mover({
moveTime: _movetime,
speed: _speed
});
})
}
// 4.转动动画模块
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)
observer.fire('finish')// 通知一下,这圈转完了
}
}, moveConfig.speed)
}
function observe(){
this.message={};
}
observe.prototype.regist=function(type,fn){
this.message[type]=fn;
}
observe.prototype.fire=function(type){
this.message[type]();
}
var _domArr=[];
var observeOb=new observe();
function htmlInit(target){
for(var i=0;i<=9;i++){
var _div=document.createElement('div');
_div.setAttribute("class","item");
_div.innerHTML=i;
target.appendChild(_div);
_domArr.push(_div);
}
}
function getFinal(){
var _num=Math.random()*10+40;
return Math.floor(_num,0);
}
function mover(moveConfig){
var nowIn=0;
var removeNum=9;
var timer=setInterval(function(){
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 _runCircle=0;
var stopNum=final%10;
var _speed=200;
mover({
moveTime:10,
speed:_speed
});
observeOb.regist('finish',function(){
var _time=0;
_speed-=50;
_runCircle++;
if(_runCircle<=_circle){
_time=10;
}else{
_time=stopNum;
}
mover({
moveTime:_time,
speed:_speed
});
})
}
htmlInit(document.getElementById('app'));
moveControll();
职责链模式
a->b->c 组织成一个流水线
目的:为了避免请求发送者与多个请求处理者耦合在一起,形成一个链条
应用场景:把操作分割成一系列模块,每个模块只处理自己的事情
// 工厂-》水果加工工厂
// 每个工人都要负责整个水果加工环节((+消毒部门)要全培训)
// 洗水果 切水果 (+消毒部门) 水果加工 水果包装
// 就是你接收的这个需求,随时可能变动:职责链
基本结构
// l把要做的事情组织为一条有序的链条,通过这条链条传递消息来完成 功能。
// 适用于不涉及到复杂异步的操作
function mode1() {
}
function mode2() {
}
function mode3() {
}
_result = mode1(_result)
_result = mode2(_result)
_result = mode3(_result)
示例(axios的拦截器-不确定需求 、利用职责链组织一个表单验证)
// axios的拦截器-不确定需求 职责链模式
// 需求:axios拦截器的设计,大家可以看成一个用给职责链的思想去处理请求
axios.interceptors.request.use(()=>{
// 成功回调
},()=>{
// 失败回调
})
axios.interceptors.response.use(()=>{
})
function Axios(){
this.interceptors = {
request: new interceptorsManner(), // 职责链是分开的
response: new interceptorsManner(), // 职责链是分开的
}
}
// 发请求
Axios.prototype.request = function() {
// 职责链模式原则:每一个模块都是依次按顺序调用,并且传递消息
var chain = [dispatchRequest, undefined];//(初始内容) 合并职责链-》最终职责链
var promise = Promise.resolve();
this.interceptors.request.handlers.forEach((interceptor)=>{
chain.unshift(interceptor.fullfilled, interceptor.rejected)// 请求拦截器(成功、失败一对)插入链条前面
})
this.interceptors.response.handlers.forEach((interceptor)=>{
chain.push(interceptor.fullfilled, interceptor.rejected)// 响应拦截器插入链条后面
})
while (){ //依次执行职责链中的每一环
// shift()执行数组最前面的,并且删除,但是会返回执行结果
promise = promise.then(chain.shift(), chain.shift());
}
}
function interceptorsManner() {
this.handlers=[]// 存放use加入的方法
}
interceptorsManner.protoType.use = function(fullfilled, rehected){
this.handlers.push({
fullfilled,
rehected
})
}
// koa中间件,职责链模式;链式调用可以看成是职责链模式,但是不准确,因为不能确定是否是模块
// 利用职责链组织一个表单验证
// 需求:有一个表单,需要先前台校验,在后端校验
input.onblur = function () {
// 只需要验证一下是不是纯数组
var _value = input.value;
var _arr = [isNumber, back, other] // 职责链数组
async function test() {
var _result = _value;
while (_arr.length>0) {
_result = await _arr.shift()(_result);
}
return _result;
}
test().then((res)=>{
// 判断res是否通过
})
}
function other() {
}
访问者模式
目的:解耦数据结构与数据的操作
应用场景:数据结构不希望与操作有关联
基本结构
// 通过定义一个访问者,代替直接访问对象, 来减少两个对象之间的耦合
var data=[];
var handler=function(){
}
handler.prototype.get=function(){
}
var vistor=function(handler,data){
handler.get(data);
}
// 不同角色访问数据
// 需求:假设有一个公司的财务报表。财务关心支出和收入,老板关心盈利
function report(){
this.income="";
this.cost="";
this.profit="";
}
function boss(){
}
boss.prototype.get=function(num){
}
function account(){
}
account.prototype.get=function(num1,num2){
}
function vistor(data,man){
var handle={
boss:function(data){
man.get(data.profit);
},
account:function(data){
account.get(data.income,data.cost);
}
}
handle[man.constructor.name](data);
}
vistor(new report(),new boss());
// 表格操作
// 需求:一个可以新增,删除的表格
function table(){
}
table.prototype.show=function(){
}
table.prototype.delete=function(id){
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(){
}
};
var arg=Array.prototype.splice(arguments);
arg.splice(0,3);
handleOb[handle].apply(this,arg);
}
总结
观察者模式:适用于不适合直接沟通的模块之间的组织
职责链模式:组织同步模块,把要做的事情划分为模块,要做的事情依次传递
访问者模式:解耦数据操作与数据结构
如果发现有错误的地方或者任何建议,欢迎评论指正