中介者模式+装饰器模式

      中介者模式的定义:通过⼀个中介者对象,其他所有的相关对象都通过该中介者对象来通信,⽽不是相互引⽤,当其中的⼀个对象发⽣改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。
例如:现实⽣活中,航线上的⻜机只需要和机场的塔台通信就能确定航线和⻜⾏状态,⽽不需要和所有⻜机通信。同时塔台作为中介者,知道每架⻜机的⻜⾏状态,所以可以安排所有⻜机的起降和航线安排。
中介者模式适⽤的场景:例如购物⻋需求,存在商品选择表单、颜⾊选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。redux,vuex 都属于中介者模式的实际应⽤,我们把共享的数据,抽离成⼀个单独的store, 每个都通过store这个中介来操作对象
⽬的就是减少耦合。
       装饰者模式的定义:在不改变对象⾃身的基础上,在程序运⾏期间给对象动态地添加⽅法。常⻅应⽤,react的⾼阶组件, 或者react-redux中的@connect 或者⾃⼰定义⼀些⾼阶组件
 
       import React from 'react'
       const withLog = Component=>{
      // 类组件
     class NewComponent extends React.Component{
     componentWillMount(){
     console.time(`CompoentRender`)
     console.log(`准备完毕了`)
     }
     render(){
     return <Component {...this.props}></Component>
     }
     
      componentDidMount(){
           console.timeEnd(`CompoentRender`)
           console.log(`渲染完毕了`)
     }
     }
     return NewComponent
      }
     export {withLog}
     @withLog
     class XX
export const connect = (mapStateToProps = state => state, mapDispatchToProps =
{}) => (WrapComponent) => {
return class ConnectComponent extends React.Component {
static contextTypes = {
store: PropTypes.object
}
constructor(props, context) {
super(props, context)
this.state = {
props: {}
}
}
componentDidMount() {
const { store } = this.context
// 当前状态 update 后, 放⼊监听器中, ⽤于下⼀次的更新(每次 dispatch 后会执⾏
subscribe 中的所有函数)
store.subscribe(() => this.update())
this.update()
}
update() {
const { store } = this.context
const stateProps = mapStateToProps(store.getState())
const dispatchProps = bindActionCreators(mapDispatchToProps,
store.dispatch)
this.setState({
props: {
...this.state.props,
...stateProps,
...dispatchProps
}
})
}
render() {
return <WrapComponent {...this.state.props}></WrapComponent>
}
}
}
假设我们在编写⼀个⻜机⼤战的游戏,随着经验值的增加,我们操作的⻜机对象可以升级成更厉害的⻜机,⼀开始这些⻜机只能发射普通的⼦弹,升到第⼆级时可以发射导弹,升到第三级时可以发射原⼦弹。
         
Function.prototype.before = function( beforefn ){
var __self = this; // 保存原函数的引⽤
return function(){ // 返回包含了原函数和新函数的"代理"函数
beforefn.apply( this, arguments ); // 执⾏新函数,且保证 this 不被劫持,新函
数接受的参数 // 也会被原封不动地传⼊原函数,新函数在原函数之前执⾏
return __self.apply( this, arguments ); // 执⾏原函数并返回原函数的执⾏结
果, // 并且保证 this 不被劫持
} }
Function.prototype.after = function( afterfn ){
var __self = this;
return function(){
var ret = __self.apply( this, arguments );
afterfn.apply( this, arguments );
return ret;
}
};
                ⽐如⻚⾯中有⼀个登录 button,点击这个 button 会弹出登录浮层,与此同时要进⾏数据上报, 来统计有多少⽤户点击了这个登录 button
 
var showLogin = function(){
console.log( '打开登录浮层' );
log( this.getAttribute( 'tag' ) );
}
var log = function( tag ){
console.log( '上报标签为: ' + tag );
(new Image).src = 'http:// xxx.com/report?tag=' + tag;
}
document.getElementById( 'button' ).onclick = showLogin;
使⽤装饰器
var showLogin = function(){
console.log( '打开登录浮层' );
}
var log = function(){
console.log( '上报标签为: ' + this.getAttribute( 'tag' ) );
}
showLogin = showLogin.after( log ); // 打开登录浮层之后上报数据
document.getElementById( 'button' ).onclick = showLogin;
装饰者模式和代理模式的结构看起来⾮常相像,这两种模式都描述了怎样为对象提供 ⼀定程度上的间接
引⽤,它们的实现部分都保留了对另外⼀个对象的引⽤,并且向那个对象发送 请求。 代理模式和装饰
者模式最重要的区别在于它们的意图和设计⽬的。代理模式的⽬的是,当直接访问本体不⽅便或者不符
合需要时,为这个本体提供⼀个替代者。本体定义了关键功能,⽽代理提供或拒绝对它的访问,或者在
访问本体之前做⼀些额外的事情。装饰者模式的作⽤就是为对 象动态加⼊⾏为。
其实Vue中的v-input,v-checkbox也可以认为是装饰器模式, 对原⽣的input和checkbox做⼀层装饰
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

     

原文地址:https://www.cnblogs.com/zhouyideboke/p/13426571.html