用多态性替换条件型
问题
您有一个条件,根据对象类型或属性执行各种操作。
解决方案
创建与条件分支匹配的子类。在它们中,创建一个共享方法,并将代码从相应的条件分支移动到该方法。然后将条件替换为相关的方法调用。结果是,根据对象类的不同,可以通过多态性来实现正确的实现。
之前
类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不问原则:与其询问对象的状态,然后根据状态执行操作,不如简单地告诉对象它需要做什么,让它自己决定如何做,这要容易得多。
删除重复的代码。你摆脱了许多几乎相同的条件句。
如果您需要添加一个新的执行变量,您所需要做的就是添加一个新的子类,而不涉及现有的代码(打开/关闭原则).
如何重构
准备重构
对于这种重构技术,您应该有一个现成的包含可选行为的类层次结构。如果你没有这样的层次结构,那就创建一个。其他技巧将有助于实现这一目标:
用子类替换类型代码.将为特定对象属性的所有值创建子类。这种方法很简单,但不太灵活,因为不能为对象的其他属性创建子类。
将类型代码替换为状态/策略.一个类将专门用于特定的对象属性,并且将从它为属性的每个值创建子类。当前类将包含对该类型对象的引用,并将执行委托给它们。
以下步骤假设您已经创建了层次结构。
重构的步骤
如果条件在一个也执行其他操作的方法中,则执行提取方法.
对于每个层次结构子类,重新定义包含条件的方法,并将相应条件分支的代码复制到该位置。
从条件句中删除这个分支。
重复替换,直到条件为空。然后删除条件并将方法声明为抽象方法。