前端设计模式分析续篇 | 青训营

128 阅读4分钟

三. Flux模式:

  • 优点:Flux模式是一种单向数据流的设计模式,通过明确的数据流动方向使得应用程序的状态管理更加可控。它通过将数据存储在单一的存储器(Store)中,使用动作(Action)进行状态更新,并通过调度器(Dispatcher)分发动作,实现了状态的一致性和可追踪性。
  • 缺点:Flux模式引入了许多概念和抽象,对于初学者来说可能有一定的学习曲线。在大型应用程序中,随着Store数量的增加,Flux模式可能导致数据流的复杂性。
  • 使用案例:React框架通常与Flux模式结合使用。通过Redux库作为状态管理器,将应用程序的状态集中存储在单一的Store中,使用动作进行状态更新。

一个例子来咯:

使用React和Flux模式的简单例子,它是一个简单的计数器应用。用的是Redux库,Redux是Flux模式的一种实现,简化了Flux模式并增加了一些功能。

首先,安装必要的库:

npm install react redux react-redux

actions.js

export const INCREMENT = 'INCREMENT';

export function increment() {
  return { type: INCREMENT };
}

reducers.js

import { INCREMENT } from './actions';

const initialState = {
  count: 0
};

function reducer(state = initialState, action) {
  switch (action.type) {
    case INCREMENT:
      return {
        ...state,
        count: state.count + 1
      };
    default:
      return state;
  }
}

export default reducer;

store.js

import { createStore } from 'redux';
import reducer from './reducers';

const store = createStore(reducer);

export default store;

Counter.js组件:

import React from 'react';
import { connect } from 'react-redux';
import { increment } from './actions';

function Counter({ count, increment }) {
  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

const mapStateToProps = state => {
  return {
    count: state.count
  };
};

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch(increment())
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter);

然后在主组件中使用Provider以使Redux store可在应用中使用:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './Counter';

ReactDOM.render(
  <Provider store={store}>
    <Counter />
  </Provider>,
  document.getElementById('root')
);

当你点击"Increment"按钮时,计数器的值就会增加。

创建了一个Redux store来保存应用的状态,定义了一个动作(INCREMENT)来改变状态,创建了一个reducer来描述如何根据动作来更新状态,还创建了一个React组件来显示计数器的值,并且当按钮被点击时派发INCREMENT动作。

四. 观察者模式: - 优点:观察者模式实现了一种松散耦合的通信机制,允许多个观察者对象订阅并接收主题对象的状态变化。当主题对象的状态发生变化时,观察者会自动收到通知并进行相应的处理,实现了对象之间的解耦。

  • 缺点:过度使用观察者模式可能导致代码的复杂性增加,难以理解和调试。在观察者模式中,观察者和主题之间可能存在多对多的关系,这可能导致难以管理和维护。
  • 使用案例:在前端开发中,观察者模式常用于事件处理和订阅/发布模式的实现。例如,使用JavaScript中的addEventListener()方法来注册事件监听器,当事件发生时,已注册的观察者将收到通知并执行相应的操作。

示例,展示如何实现一个事件发布/订阅系统:

// 定义一个主题对象
class Subject {
  constructor() {
    this.observers = []; // 观察者列表
  }

  // 注册观察者
  addObserver(observer) {
    this.observers.push(observer);
  }

  // 移除观察者
  removeObserver(observer) {
    const index = this.observers.indexOf(observer);
    if (index !== -1) {
      this.observers.splice(index, 1);
    }
  }

  // 通知观察者
  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

// 定义一个观察者对象
class Observer {
  constructor(name) {
    this.name = name;
  }

  // 观察者接收到通知后的处理方法
  update(data) {
    console.log(`${this.name} 收到通知,数据为:${data}`);
  }
}

// 创建主题对象
const subject = new Subject();

// 创建观察者对象
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
const observer3 = new Observer('Observer 3');

// 注册观察者
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.addObserver(observer3);

// 发布通知
subject.notify('Hello, observers!');

示例中,定义了一个Subject类作为主题对象,它维护一个观察者列表。Subject类有三个方法:

  • addObserver(observer):用于注册观察者,将观察者对象添加到观察者列表中。
  • removeObserver(observer):用于移除观察者,从观察者列表中删除指定的观察者对象。
  • notify(data):用于通知观察者,遍历观察者列表并调用每个观察者的update方法,将数据作为参数传递给观察者。

我还定义了一个Observer类作为观察者对象,它有一个update方法用于接收通知并进行相应的处理。

在示例中,我创建了一个主题对象subject和三个观察者对象observer1observer2observer3。然后,我们将观察者注册到主题对象中,使它们成为主题的观察者。最后,我们通过调用subject.notify()方法发布通知,所有注册的观察者都会收到通知并执行相应的操作。

这个示例演示了观察者模式的基本原理。通过使用观察者模式,可以实现一个松散耦合的通信机制,主题对象和观察者对象之间的关系变得灵活,主题对象的状态变化可以自动通知到所有观察者对象,观察者可以根据需要进行注册和移除。