直播平臺開發中,策略模式和釋出訂閱模式的使用

雲豹科技程式設計師發表於2021-12-16

什麼是設計模式

設計模式是一種可複用的解決方案,用於解決直播平臺開發中遇到的常見問題;
通俗的講 設計模式是一套被反覆使用,多數人知曉的,經過分類的,程式碼設計經驗的總結。是在直播平臺開發過程中,針對特殊問題/場景的更優的解決方案

怎麼用

設計模式的核心操作是去觀察直播平臺開發整個邏輯裡面的變與不變,然後將變與不變分離,達到使變化的部分靈活、不變的地方穩定的目的。

策略模式

它的定義很精簡:一個類的行為或其演算法可以在執行時更改。我們把它降維到直播平臺開發層面,用人話翻譯一下就是,執行時我給你這個類的方法傳不同的“key”,你這個方法會執行不同的業務邏輯。
細品一下,和if else好像沒啥區別?

  • 什麼時候用:

在某些直播平臺開發規範裡有這樣一條 :超過 3 層的 if-else 的邏輯判斷程式碼可以使用衛語句、策略模式、狀態模式等來實現。

說概念有點幹 舉個小例子? :

有這樣一個場景,在請求某個table資料的時候,後端有時會返回狀態碼,前端需要根據不同的狀態碼來展示不同的語句
在這裡插入圖片描述

呃。 一言難盡。。。也不知道當時怎麼想的,就硬if else,你好歹用個switch也比這個強啊。那個any型別也就不提了
這樣寫其實也不是不行,對使用者來說,最起碼執行不報錯,效果也符合預期。但對直播平臺開發開發來說,首先程式碼過於冗餘,不易閱讀; 其次如果後期要再新增/修改某個狀態,我只能繼續else if,不利於擴充和維護;
既然不行我們就改改:

const generateStatus = (text: string) => {
  switch(text) {
    case 'STATUS_OK':
      return { styles: globalStyle.suc, text: '執行' };
    case 'STATUS_UNKNOWN':
      return { styles: globalStyle.info, text: '未知狀態' };
    case 'STATUS_FAIL':
      return { styles: globalStyle.fail, text: '故障', };
    case 'STATUS_STOPPED':
      return { styles: globalStyle.stop, text: '停止' };
    default: return { styles: '', text };
  }};render: (status: string) => {
  const { styles, text } = generateStatus(status); 
  return (
    <span className={styles}>{text}</span>
  );}

感覺好多了。。。
當然,除了用switch這種寫法,還可以用上面主要講的策略模式:

// 1.建立一個物件const statusData = {
  'STATUS_OK': { styles: globalStyle.suc, text: '執行' },
  'STATUS_UNKNOWN': { styles: globalStyle.info, text: '未知狀態' },
  'STATUS_FAIL': { styles: globalStyle.fail, text: '故障' },
  'STATUS_STOPPED': { styles: globalStyle.stop, text: '停止', },};render: (status: string) => {
  return (
    <span className={statusData[status]?.styles ?? ''}>{statusData[status]?.text ?? text}</span>
  );}

延伸一下:
這裡是把status引數當成key值來拿到對應的資料。但在有些時候,上面這種寫法可能不能滿足直播平臺開發的要求。
這裡找不到合適的例子,我把需求魔改一下,比如:當前的status是個物件,且沒有具有唯一性的屬性,比如:

type IType = 'uproxy' | 'ushard';type ICode = 'STATUS_OK' | 'STATUS_UNKNOWN' | 'STATUS_FAIL' | 'STATUS_STOPPED'render: (status: {
	type: IType,
  code: ICode,}) => {
	//....比如這種情況;};// 這種情況下也可以用map來實現 (map和object的區別是map可以 value: value);const statusData = new Map([
  [{type: 'uproxy', code: 'STATUS_OK'}, {styles: globalStyle.suc, text: 'uproxy執行'}];
  [{type: 'ushard', code: 'STATUS_OK'}, {styles: globalStyle.suc, text: 'ushard執行'}];])render: (status) => {
  const statusData = [...statusData].find(([key,value]) => 
    key.type === status.type && key.code === status.code  );
	return (
    <span className={statusData[1].styles}>{statusData[1].text}</span>
	);}

總結:

直播平臺開發使用策略模式的優點是將一個個邏輯封裝起來,並可以任意的替換。在邏輯較多的場景下,程式碼比直接if else好維護些;
但從上面的例子也可以看出,即使用了策略模式,該寫的邏輯還是要寫,並不能減少很多的程式碼量,並且策略越多,拆分組合的過程就會越複雜,所以在使用過程中要合理運用。針對直播平臺開發不同的場景,選擇合適的解決方案。

釋出訂閱模式

釋出-訂閱模式其實是一種物件間一對多的依賴關係,當一個物件的狀態傳送改變時,所有依賴於它的物件都將得到狀態改變的通知。
不知道大家有沒有發現,專案裡的eventEmitter就是通過釋出-訂閱模式來實現的,下面是我從專案裡貼上的程式碼

class EventEmitter {
  constructor() {
    this.events = {}; //事件儲存中心;
    this.addListener.bind(this);
    this.removeListener.bind(this);
    this.emit.bind(this);
  }
  protected events: {[key: string]: any};
  public addListener(event: string, listener: (...args: any[]) => void) {
    // 由於一個事件可能註冊多個回撥函式,所以使用陣列來儲存事件佇列
    (this.events[event] || (this.events[event] = [])).push(listener);
  }
  public removeListener(event: string, listener: (...args: any[]) => void) {
    if (this.events[event]) {
      this.events[event].splice(this.events[event].indexOf(listener), 1);
    }
  }
  //釋出事件。 args 用於收集釋出事件時傳遞的引數
  public emit(event: string, ...args: any[]) {
    if (this.events[event]) {
      this.events[event].forEach((listener: any) => {
        listener(...args);
      });
    }
  }}const eventEmitter = new EventEmitter();export default eventEmitter;

要使用的話也很簡單,類似於js的addEventListener和removeEventListener;
? : 在直播平臺開發某些場景下我們需要監聽一下localstorate的變化,但是js原生並沒有這樣的api來達到我們的目的。我們可以把localstorage的setItem方法重新給封裝一下,然後通過EventEmitter來監聽localStorage的變化;

//1.設定監聽React.useEffect(() => {
  eventEmitter.addListener('storageEvent', handleStorageChange);
  return () => {
    eventEmitter.removeListener('storageEvent', handleStorageChange);
  };}, []);//2.封裝一個自定義的localStorage的setItem的方法;//每次在localStorage中寫入/修改資料的時候都會呼叫emit函式釋出事件,並把key,value給傳遞過去;const setItem = (key, value) {
  eventEmitter.emit('storageEvent', {key, value});
  return localStorage.setItem(key, value);}

以上便是“直播平臺開發中,策略模式和釋出訂閱模式的使用”的全部內容,希望對大家由幫助。
本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2848145/,如需轉載,請註明出處,否則將追究法律責任。

相關文章