天天看点

中介者模式+装饰器模式

      中介者模式的定义:通过⼀个中介者对象,其他所有的相关对象都通过该中介者对象来通信,⽽不是相互引⽤,当其中的⼀个对象发⽣改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。

例如:现实⽣活中,航线上的⻜机只需要和机场的塔台通信就能确定航线和⻜⾏状态,⽽不需要和所有⻜机通信。同时塔台作为中介者,知道每架⻜机的⻜⾏状态,所以可以安排所有⻜机的起降和航线安排。

中介者模式适⽤的场景:例如购物⻋需求,存在商品选择表单、颜⾊选择表单、购买数量表单等等,都会触发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;

装饰者模式和代理模式的结构看起来⾮常相像,这两种模式都描述了怎样为对象提供 ⼀定程度上的间接

引⽤,它们的实现部分都保留了对另外⼀个对象的引⽤,并且向那个对象发送 请求。 代理模式和装饰

者模式最重要的区别在于它们的意图和设计⽬的。代理模式的⽬的是,当直接访问本体不⽅便或者不符

合需要时,为这个本体提供⼀个替代者。本体定义了关键功能,⽽代理提供或拒绝对它的访问,或者在

继续阅读