2013-07-10 26 views
0

A Request类有一个属性colorType它可以是不同的颜色。根据颜色的类型,它会涉及到不同的处理方式。如何更好地设计此代码和逻辑

这里是控制器代码:

def colorInstance = Color(params) 
//validates and checks the params. Also, based on some logic sets the `colorType` property 
//to be appropriate color 
if (colorInstnace.validate()) 
{ 
    colorService.processColor(colorInstance) 
} 

这里是colorService代码:

void processColor(Color colorInstance) { 
    if (colorInstance.colorType == "green") 
     processGreen(colorInstance) 
    else if (colorInstance.colorType == "red") 
     processRed(colorInstance) 
    .... 
    ...... 
} 

processGreen(Color colorInstance) { 
    //common code 
    //code specific to colortypes that are GREEN 
    //more common code 
} 

processRed(Color colorInstance) { 
    //common code 
    //code specific to colortypes that are RED 
    //more common code 
} 

问题

  1. 我如何更改代码的服务,使我不必复制粘贴所有processXXX中的代码方法?
  2. 如何消除processColor方法中的if/elseif

回答

1

服务类可以有以下实现。 groovy中的Switch case可以处理任何值,你不需要使用任何原始数据类型。

void processColor(Color colorInstance) { 
    processCommonCodeBefore(colorInstance) 
    processColorSpecificCode(colorInstance) 
    processCommonCodeAfter(colorInstance)  
} 

processCommonCodeBefore(Color colorInstance) { 
    //common code 
} 

processCommonCodeAfter(Color colorInstance) { 
    //common code 
} 

processColorSpecificCode(Color colorInstance) { 
    switch(colorInstance.colorType){ 
     case 'green': 
      processGreen(colorInstance) 
      break 
     case 'blue': 
      processBlue(colorInstance) 
      break 
     default: 
      processDefault(colorInstance) 
    }  
} 

这样,服务类中的所有方法都可以高效地进行单元测试。

1

我认为如果您使用整型常量来代替它会更容易。

// you could use actual RGB too.. then red would be 0xff0000 
static final int RED = 0 
static final int BLUE = 1 
static final int GREEN = 2 

然后在colorService,你可以尝试这样的事情......

void processColor(Color colorInstance) { 
    commonMethodOne(); 

    switch(colorInstance.colorType){ 

    case RED: 
    //Handle the red color 
    case BLUE: 
    // Handle the blue color, etc. 

    } 

    commonMethodTwo(); 
} 

commonMethodOne(){ 
    //Here is code that gets executed regardless of Color 
} 

commonMethodTwo(){ 
    //Here is more code that gets executed regardless of Color 
} 
+0

如果他使用Groovy,他应该继续使用类型安全的枚举,而不是整型常量。 – chrylis

1

即使答案已被接受,我想指出一个替代解决方案,使用enum代替ColorType

class Color { 
    ColorType colorType 
    ... 
} 

enum ColorType { 
    blue { 
     @Override void process(Color color) { 
      // code for processing blue 
     } 
    }, 
    green { 
     @Override void process(Color color) { 
      // code for processing green 
     } 
    }, 
    red, 
    yellow 

    void process(Color color) { 
     // used for red and yellow 
    } 
} 

像Java中你可以添加方法,以枚举(如process(Color color))。您也可以针对某些枚举常量重写这些方法。在此示例中,枚举值blue和​​将覆盖process(Color color)方法。

使用这种方法,你就可以做到这一点:

void processColor(Color colorInstance) { 
    commonMethod(colorInstance) 
    colorInstance.colorType.process(colorInstance) 
    otherCommonMethod(colorInstance) 
} 

这个例子的问题是,它创造ColorColorType应避免其之间的循环依赖。但根据您的实施情况,可能会从ColorType.process()方法中删除color参数来解决此问题。

我只是想指出的是,重写枚举的方法有时是针对这种情况,一个非常有用的功能:-)

+0

'Color'是一个由OP的问题中的grails域类表示的持久实体,它应该将实体作为类的成员。因此,'colorType'将代表'COLOR'表中的'COLOR_TYPE'列,尽管你的方法对于POGO类可能很方便。 – dmahapatro

+0

嗯,我不明白你的意思。您可以在域类中引用/保存枚举而不会出现问题。 – micha