圣诞大减价开始了!

用多态性替换条件型

问题

您有一个条件,根据对象类型或属性执行各种操作。

解决方案

创建与条件分支匹配的子类。在它们中,创建一个共享方法,并将代码从相应的条件分支移动到该方法。然后将条件替换为相关的方法调用。结果是,根据对象类的不同,可以通过多态性来实现正确的实现。

之前
类Bird{//…double getSpeed() {switch (type) {case EUROPEAN:返回getBaseSpeed();case AFRICAN:返回getBaseSpeed() - getLoadFactor() * numberOfCoconuts;case norway: return (isnails) ?0: getBaseSpeed(电压);}抛出新的RuntimeException("应该不可达");}}
抽象类Bird{//…抽象双getSpeed();}类欧洲扩展鸟{双getSpeed(){返回getBaseSpeed();}}类非洲扩展鸟{双getSpeed(){返回getBaseSpeed() - getLoadFactor() * numberOfCoconuts;}}类挪威蓝扩展鸟{双getSpeed(){返回(ispinned) ?0: getBaseSpeed(电压);}} //在客户端代码中speed = bird.getSpeed();
之前
公共类Bird{//…public double GetSpeed() {switch (type) {case EUROPEAN:返回GetBaseSpeed();case AFRICAN:返回GetBaseSpeed() - GetLoadFactor() * numberOfCoconuts;case norwegian gian_blue: return isnail ?0: GetBaseSpeed(电压);默认:抛出新的异常(“应该不可达”);}}}
公共抽象类Bird{//…GetSpeed();}类欧洲:鸟{公共覆盖双GetSpeed(){返回GetBaseSpeed();}}类非洲:鸟{公共覆盖双GetSpeed(){返回GetBaseSpeed() - GetLoadFactor() * numberOfCoconuts;}}类挪威蓝色:鸟{公共覆盖双GetSpeed(){返回ispinned ?0: GetBaseSpeed(电压);}} //在客户端代码中speed = bird.GetSpeed();
之前
类Bird{//…公共函数getSpeed(){开关($this->类型){case EUROPEAN:返回$this->getBaseSpeed();case AFRICAN:返回$this->getBaseSpeed() - $this->getLoadFactor() * $this->numberOfCoconuts;返回($this-> isnails) ?0: $this->getBaseSpeed($this->电压);}抛出新的异常(“应该不可达”);} //…}
抽象类Bird{//…抽象函数getSpeed();/ /……}类欧洲扩展鸟{公共函数getSpeed(){返回$this->getBaseSpeed();}}类African extends Bird{公共函数getSpeed(){返回$this->getBaseSpeed() - $this->getLoadFactor() * $this->numberOfCoconuts;}}类挪威蓝扩展鸟{公共函数getSpeed(){返回($this-> ispinned) ?0: $this->getBaseSpeed($this->电压);}} //在客户端代码中。$speed = $bird->getSpeed();
之前
班级鸟:#…def getSpeed(self): if self。type == EUROPEAN:返回self. getbasespeed () elif self. getbasespeed ()type == AFRICAN:返回self. getbasespeed () - self. getloadfactor () * self. getbasespeed ()数椰子elif self。type == norwegian gian_blue:如果self返回0。ispinned else self.getBaseSpeed(self.voltage) else:引发异常(“应该不可达”)
班级鸟:#…def getSpeed(self): pass类欧洲(Bird): def getSpeed(self):返回self. getbasespeed()类非洲(Bird): def getSpeed(self):返回self. getbasespeed () - self. getloadfactor () * self。norgianblue (Bird): def getSpeed(self):如果self返回0。isnail else self.getBaseSpeed(self.voltage) #在客户端代码中的某处speed = bird.getSpeed()
之前
类Bird{//…getSpeed(): number {switch (type) {case EUROPEAN:返回getBaseSpeed();case AFRICAN:返回getBaseSpeed() - getLoadFactor() * numberOfCoconuts;case norway: return (isnails) ?0: getBaseSpeed(电压);}抛出新的错误(“应该不可达”);}}
抽象类Bird{//…抽象getSpeed():数字;}类欧洲扩展鸟{getSpeed():数字{返回getBaseSpeed();}}类非洲扩展鸟{getSpeed():数字{返回getBaseSpeed() - getLoadFactor() * numberOfCoconuts;}}类挪威蓝扩展鸟{getSpeed():数字{返回(ispinned) ?0: getBaseSpeed(电压);}} //在客户端代码中让speed = bird.getSpeed();

为什么重构

如果你的代码包含操作符执行各种不同的任务,这种重构技术会有所帮助:

  • 它所实现的对象或接口的类

  • 对象字段的值

  • 调用对象方法之一的结果

如果出现了新的对象属性或类型,则需要在所有类似的条件中搜索并添加代码。因此,如果在对象的所有方法中分散存在多个条件,这种技术的好处就会成倍增加。

好处

  • 这种技术坚持Tell-Don不问原则:与其询问对象的状态,然后根据状态执行操作,不如简单地告诉对象它需要做什么,让它自己决定如何做,这要容易得多。

  • 删除重复的代码。你摆脱了许多几乎相同的条件句。

  • 如果您需要添加一个新的执行变量,您所需要做的就是添加一个新的子类,而不涉及现有的代码(打开/关闭原则).

如何重构

准备重构

对于这种重构技术,您应该有一个现成的包含可选行为的类层次结构。如果你没有这样的层次结构,那就创建一个。其他技巧将有助于实现这一目标:

  • 用子类替换类型代码.将为特定对象属性的所有值创建子类。这种方法很简单,但不太灵活,因为不能为对象的其他属性创建子类。

  • 将类型代码替换为状态/策略.一个类将专门用于特定的对象属性,并且将从它为属性的每个值创建子类。当前类将包含对该类型对象的引用,并将执行委托给它们。

以下步骤假设您已经创建了层次结构。

重构的步骤

  1. 如果条件在一个也执行其他操作的方法中,则执行提取方法

  2. 对于每个层次结构子类,重新定义包含条件的方法,并将相应条件分支的代码复制到该位置。

  3. 从条件句中删除这个分支。

  4. 重复替换,直到条件为空。然后删除条件并将方法声明为抽象方法。

Baidu
map