当前位置:网站首页>Typescript: use polymorphism instead of switch and other conditional statements
Typescript: use polymorphism instead of switch and other conditional statements
2022-06-26 06:58:00 【Code Taoist】
Use OOP Principles for writing better code .
In limine , I use as much as I can switch sentence . For me, , It looks perfect , Until one day I read a book called “ Tidiness code ” The book of .Robert C. Martin The book clearly explains why switch Statement can be a bad structure , And why we might reconsider and stop using them anywhere .
With the passage of time and the accumulation of experience , I use less and less switch sentence , later , I don't see any reason to use them . In this paper , I would like to share an alternative that I have used in my project switch Method of statement . It is called polymorphism , It's also OOP One of the principles of .
Why reconsider using switch sentence ?
switch
Statements always cause methods to be verbose , Dozens of conditions , Each instruction requires at least a few lines of code plus break.Robert C. Martin In his 《 Tidiness code 》 It is said in a book that this method “ Use as little as possible ”.Besides ,switch Statements are not readable and extensible .
Must filter through hundreds of criteria ( Multiple cases —— Single operation ), This is not user friendly , And may confuse others .
In a switch Statements can be mixed with completely different logic , Of course, this is wrong , Because of the method “ You should only do one thing and do it well ”.
What do we have ? One switch sentence ?
This is the initial code we will refactor in this article . We have a switch Statement and a code to enumerate various fruits .
export enum Fruits {
Apple = 1,
Lemon = 2,
Orange = 3,
Banana = 4,
}
function getPrice(fruit: Fruits): number {
let result: number;
switch (fruit) {
case Fruits.Banana:
result = 11.1;
break;
case Fruits.Lemon:
result = 6.5;
break;
case Fruits.Orange:
result = 7.7;
break;
case Fruits.Apple:
result = 5.2;
break;
default:
result = 0;
}
return result;
}
We can get rid of switch sentence , Because we just need to enumerate .
Let's get rid of switch Statement!
First , Let's add a new one called Fruit The abstract class of , Express the basic entity in terms of price .
export abstract class Fruit {
protected constructor(readonly price: number) {}
}
Fruits Classes should be abstract , Because we don't want to create base class instances . The inherited class will provide the value of the price .
export const Fruits: Record<FruitType, new () => Fruit> = {
Apple: class extends Fruit {
constructor() {
super(5.2);
}
},
Banana: class extends Fruit {
constructor() {
super(11.1);
}
},
Lemon: class extends Fruit {
constructor() {
super(6.5);
}
},
Orange: class extends Fruit {
constructor() {
super(7.7);
}
},
};
Here we can see that we used Record
Utility type .
Now? , Let's add a function that provides the correct constructor .
const findFruitConstructor = (fruitEnum: FruitEnum): new () => Fruit => Fruits[fruitEnum];
Start the first test :
const Banana = findFruitConstructor(FruitEnum.Banana);
console.log(new Banana());
// or just
console.log(new Fruits[FruitEnum.Apple]());
Overloaded constructor factory function
Sometimes , It is convenient to pass strings instead of enumerating values . for example , We may start from HTML Get a string from the template , We should return the price for it .
But before we update the constructor factory function , We need to add another function to help us use enumeration :
function enumToEntries(enumSrc: any): [string, number][] {
const onlyNames = (value: string) =>
typeof enumSrc[value] === "number";
const asEntry = (value: string) =>
[value, parseInt(enumSrc[value])] as [string, number];
return Object.keys(enumSrc).filter(onlyNames).map(asEntry);
}
It simply enumerates and returns an array with tuples . Each tuple consists of an enumeration name and a value .
To use strings and enumeration values , We need to update our constructor factory function :
function findFruitConstructor(
constructorName: string | FruitEnum
): new () => Fruit | never {
const fruitEntries = enumToEntries(FruitEnum);
const currentEntry = fruitEntries.find((entry: [string, number]) => {
return entry.includes(constructorName);
});
const result = currentEntry
? () => Fruits[currentEntry[1] as FruitEnum]
: () => {
throw new Error('Given fruit doesn't exist.')
};
return result();
}
Let's test by passing a string value findFruitConstructor
function :
const Banana = findFruitConstructor('Banana');
console.log(new Banana());
// Will throw an error
const NotExisting = findFruitConstructor('NotExisting');
console.log(new NotExisting());
Use Nullable Patterns provide default behavior
If we somehow get the name of a constructor that doesn't exist , What will happen ?
We'll get a mistake .
To prevent this and set the default behavior for non-existent fruits , We can use Nullable Patterns instead of errors .
Let's add a Nullable
Interface :
interface Nullable {
isNull(): boolean;
}
Fruit Class should implement what must be returned Nullable
Interface and return false Of .isNull()
Method .
abstract class Fruit implements Nullable {
protected constructor(readonly price: number) {}
isNull(): boolean {
return false;
}
}
We also need to add NullableFruit
, This class represents a fruit without behavior :
class NullableFruit extends Fruit {
constructor() {
super(0);
}
isNull(): boolean {
return true;
}
}
Now we need to return one NullableFruit
Constructor instead of throwing an error .
function findFruitConstructor(
constructorName: string | FruitEnum
): new () => Fruit {
const fruitEntries = enumToEntries(FruitEnum);
const currentEntry = fruitEntries.find((entry: [string, number]) => {
return entry.includes(constructorName);
});
return currentEntry ? Fruits[currentEntry[1] as FruitEnum] : NullableFruit;
}
This is the final demo:
const Banana = findFruitConstructor('Banana');
const banana = new Banana();
console.log(banana); // { "price": 11.1 }
console.log(banana.isNull()); // false
// Won't throw an error
const NotExisting = findFruitConstructor('NotExisting');
const notExistingFruit = new NotExisting();
console.log(notExistingFruit); // { "price": 0 }
console.log(notExistingFruit.isNull()); // true
It seems to work as expected . Besides , We have added many useful features in this process , And you can continue to add more functions .
边栏推荐
- Decision tree learning notes
- [image fusion] multimodal medical image fusion based on coupled feature learning with matlab code
- 遇到女司机业余开滴滴,日入500!
- One chip realizes functions such as spray 𞓜 ws2812 drive | key touch | LED display | voice broadcast chip and simplifies the design of humidifier products
- Shell编程-用户信息管理
- [004] [stm32] MDK project configuration and commissioning
- SQL基础
- Bugku练习题---MISC---富强民主
- [golang] time related
- The four cores of the browser: Trident, gecko, WebKit, blink
猜你喜欢
Past events of Xinhua III
【图像融合】基于耦合特征学习的多模式医学图像融合附matlab代码
[image enhancement] image defogging based on artificial multiple exposure fusion amef with matlab code
Invalid problem of self defined map used by Gaode map
Massive log collection tool flume
STM 32 uses cube to generate Tim to trigger ADC and transmit through DMA
[digital signal processing] basic sequence (unit step sequence | relationship between unit step sequence and unit pulse sequence | rectangular sequence | relationship between rectangular sequence and
【元胞自动机】基于元胞自动机实现高速公路收费站交通流问题附matlab代码
Bugku exercise ---misc--- prosperity, strength and democracy
PyTorch搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
随机推荐
专业课-代码题记录
Numpy learning challenge level 4 - numpy array attribute
The four cores of the browser: Trident, gecko, WebKit, blink
SQL 查询语句
Load balancer does not have available server for client: userservice problem solving
Go language learning notes 1.1
Go language learning notes 1.2- variables
Research Report on market supply and demand and strategy of China's pallet scale industry
Research Report on China's surfactant market demand and future investment opportunities 2022
LabVIEW Arduino TCP/IP遠程智能家居系統(項目篇—5)
Research Report on market supply and demand and strategy of natural organic beauty industry in China
Research Report on pallet handling equipment industry - market status analysis and development prospect forecast
MySQL 数据库的小白安装与登录
How to transfer database data to check box
NumPy学习挑战第四关-NumPy数组属性
Research Report on market supply and demand and strategy of Chinese amyl cinnamaldehyde (ACA) industry
SQL基础
Market scale forecast and investment risk forecast report of China's securities operating institutions 2022-2027
【图像分割】基于最大主曲率实现视网膜眼底图像中的血管提取附matlab代码
[cellular automata] Based on cellular automata, realize the traffic flow problem of expressway toll station, with matlab code