iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 15
1
Software Development

為什麼世界需要Typescript系列 第 15

利用抽象類別取代if else - 15

  • 分享至 

  • twitterImage
  •  

用抽象類別(abstract class) 方法取代if else

先定義一個基本的抽象類別

abstract class ForSale {
   abstract getDiscount(): number;
}

定義折扣一本書的物件

class OneBookForSale extends ForSale {
   getDiscount(): number {
      return 1;
   }
}

定義折扣二本書的物件

class TwoBooksForSale extends ForSale {
   getDiscount(): number {
      return 0.95;
   }
}

定義折扣三本書, 四本書, 五本書的物件

class ThreeBooksForSale extends ForSale {
   getDiscount(): number {
      return 0.9;
   }
}

class FourBooksForSale extends ForSale {
   getDiscount(): number {
      return 0.8;
   }
}

class FiveBooksForSale extends ForSale {
   getDiscount(): number {
      return 0.75;
   }
}

class MoreThanFiveBooksForSale extends ForSale {
   getDiscount(): number {
      return 0.75;
   }
} 

建立好上面的物件之後, 再回頭修改 getPrice 方法

class Bookstore {
   private _forSales: {[books: number]: ForSale} = {
      1: new OneBookForSale(),
      2: new TwoBooksForSale(),
      3: new ThreeBooksForSale(),
      4: new FourBooksForSale(),
      5: new FiveBooksForSale(),
   };

   getPrice(books: number): number {
      let sale = this._forSales[books];
      if( sale == undefined ) {
         sale = new MoreThanFiveBooksForSale();
      }
      return books * 100 * sale.getDiscount();
   }
}

將這些物件註冊到字典中, 根據key 取得對應的物件, 然後呼叫統一共同的方法 getDiscount() 取得折扣.

用介面方法(interface) 方法取代if else

跟上面的抽象類別方法很像, 只是這裡改成interface

interface IForSale {
   getDiscount(): number;
}

然後每一個新物件就實作(implements) IForSale 這個介面.

class OneBookForSale implements IForSale {
   getDiscount(): number {
      return 1;
   }
}

class TwoBooksForSale implements IForSale {
   getDiscount(): number {
      return 0.95;
   }
}

class ThreeBooksForSale implements IForSale {
   getDiscount(): number {
      return 0.9;
   }
}

class FourBooksForSale implements IForSale {
   getDiscount(): number {
      return 0.8;
   }
}

class FiveBooksForSale implements IForSale {
   getDiscount(): number {
      return 0.75;
   }
}

class MoreThanFiveBooksForSale implements IForSale {
   getDiscount(): number {
      return 0.75;
   }
} 

同樣的, 在字典的地方改成如下

 private _forSales: {[books: number]: IForSale} {
   1: new OneBookForSale(),
   2: new TwoBooksForSale(),
   3: new ThreeBooksForSale(),
   4: new FourBooksForSale(),
   5: new FiveBooksForSale(),
};

責任鏈模式 (Chain of responsibility Pattern)

責任鏈模式是一種軟體設計模式, 它的特色就是

  • 將一群物件(Class) 串接起來
  • 每一個物件(Class) 都有機會來處理一項請求(Request)
  • 每一個物件(Class) 處理請求的時候, 假如自己可以處理就結束了, 無法處理就將請求(Request)丟給下一個物件處理.

首先要設計一個基本抽象類別Class 讓它們串起來

abstract class ChainForSale {
   private _next: ChainForSale = null;
   
   constructor(next: ChainForSale) {
      this._next = next;
   }

   getDiscount(books: number): number {
      let next = this._next;
      if( next == null) {
         throw new Error("can't handle.");
      }
      return next.getDiscount(books);
   }
}

相同的基本類別(Class) 透過建構元(constructor) 來決定下一個是誰, 這樣就可以把一群處理物件(Class) 串起來.


上一篇
消滅多個if 的方法 - 14
下一篇
責任鏈模式 - 16
系列文
為什麼世界需要Typescript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言