当前位置:网站首页>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 ?
switchStatements 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()); // trueIt seems to work as expected . Besides , We have added many useful features in this process , And you can continue to add more functions .
边栏推荐
- LabVIEW Arduino tcp/ip remote smart home system (project part-5)
- Shell programming - user information management
- SHOW语句用法补充
- 【图像检测】基于形态学实现图像目标尺寸测量系统附matlab代码
- MYSQL触发器要如何设置,简单教程新手一看就会
- Numpy learning challenge level 1 - Download and installation of numpy
- Spark3.3.0 source code compilation supplement - Crazy certificate problem
- Market scale forecast and investment risk forecast report of China's securities operating institutions 2022-2027
- Invalid problem of self defined map used by Gaode map
- cocoscreator播放Spine动画
猜你喜欢

【元胞自动机】基于元胞自动机实现高速公路收费站交通流问题附matlab代码

Mysql操作数据库

Bugku exercise ---misc--- prosperity, strength and democracy

Numpy learning challenge level 4 - numpy array attribute

STM 32 uses cube to generate Tim to trigger ADC and transmit through DMA

LabVIEW Arduino TCP/IP遠程智能家居系統(項目篇—5)
![[micro service series] protocol buffer dynamic analysis](/img/86/357d55c77cc67d6413af2de59bf395.png)
[micro service series] protocol buffer dynamic analysis

Load balancer does not have available server for client: userservice problem solving

MySQL delete in without index

报错问题Parameter index out of range(0 < 1) (1 > number of parameters,which is 0
随机推荐
How to choose securities companies for stock speculation? Is it safe to open a mobile account?
Interviewer: what is the difference between a test plan and a test plan?
SQL基础
高德地图使用自定义地图无效问题
Format one insert per line using mysqldump- Using mysqldump to format one insert per line?
China's audio industry competition trend outlook and future development trend forecast report 2022 Edition
[image segmentation] blood vessel extraction from retinal fundus images based on maximum principal curvature with matlab code
Six stones Management: exaggerating the achievements, whether the parties themselves know
【图像检测】基于Itti模型实现图像显著性检测附matlab代码
Easyar use of unity
遇到女司机业余开滴滴,日入500!
MySQL (III)
SQL中空值的判断
STM 32 uses cube to generate Tim to trigger ADC and transmit through DMA
【yolov4】基于yolov4深度学习网络目标检测MATLAB仿真
[004] [stm32] MDK project configuration and commissioning
My SQL (II)
同花顺究竟如何开户,网上开户是否安全么?
Research Report on market supply and demand and strategy of Chinese amyl cinnamaldehyde (ACA) industry
[image detection] image target size measurement system based on morphology with matlab code